lib/ldap_resource.rb in dm-ldap-adapter-0.3.5 vs lib/ldap_resource.rb in dm-ldap-adapter-0.4.0.alpha2

- old
+ new

@@ -1,15 +1,109 @@ require 'ldap/digest' require 'dm-core' require 'ldap/array' module DataMapper - module Resource - module ClassMethods - + module Model + + def load(records, query) + repository = query.repository + repository_name = repository.name + fields = query.fields + discriminator = properties(repository_name).discriminator + no_reload = !query.reload? + + field_map = fields.map { |property| [ property, property.field ] }.to_hash + + records.map do |record| + identity_map = nil + key_values = nil + resource = nil + + case record + when Hash + # remap fields to use the Property object + record = record.dup + field_map.each { |property, field| record[property] = record.delete(field) if record.key?(field) } + + model = discriminator && discriminator.load(record[discriminator]) || self + model_key = model.key(repository_name) + + resource = if model_key.valid?(key_values = record.values_at(*model_key)) + identity_map = repository.identity_map(model) + identity_map[key_values] + end + + resource ||= model.allocate + + fields.each do |property| + next if no_reload && property.loaded?(resource) + + value = record[property] + + # TODO: typecasting should happen inside the Adapter + # and all values should come back as expected objects + if property.respond_to?(:load_with_resource) + # hack to allow mutable types which are able to reset + # the attribute to make them dirty + value = property.load_with_resource(value, resource) + else + value = property.load(value) + end + + property.set!(resource, value) + end + + when Resource + model = record.model + model_key = model.key(repository_name) + + resource = if model_key.valid?(key_values = record.key) + identity_map = repository.identity_map(model) + identity_map[key_values] + end + + resource ||= model.allocate + + fields.each do |property| + next if no_reload && property.loaded?(resource) + + property.set!(resource, property.get!(record)) + end + end + + resource.instance_variable_set(:@_repository, repository) + + if identity_map + resource.persisted_state = Resource::State::Clean.new(resource) unless resource.persisted_state? + + # defer setting the IdentityMap so second level caches can + # record the state of the resource after loaded + identity_map[key_values] = resource + else + resource.persisted_state = Resource::State::Immutable.new(resource) + end + + resource + end + end + + module LdapResource + + Model.append_inclusions self + + # authenticate the current resource against the stored password + # @param [String] password to authenticate + # @return [TrueClass, FalseClass] whether password was right or wrong + def authenticate(password) + ldap.authenticate(ldap.dn(self.class.dn_prefix(self), + self.class.treebase), + password) + end + # if called without parameter or block the given properties get returned. - # if called with a block then the block gets stored. if called with new + # if called with a block then the block gets stored. if called with new # properties they get stored. if called with a Resource then either the # stored block gets called with that Resource or the stored properties get # returned. # @param [Hash,DataMapper::Resource] properties_or_resource either a Hash with properties, a Resource or nil # @param [block] &block to be stored for later calls when properties_or_resource is nil @@ -25,13 +119,13 @@ end else @ldap_properties = block end end - + # if called without parameter or block the given treebase gets returned. - # if called with a block then the block gets stored. if called with a + # if called with a block then the block gets stored. if called with a # String then it gets stored. if called with a Resource then either the # stored block gets called with that Resource or the stored String gets # returned. # @param [String,DataMapper::Resource] treebase_or_resource either a String, a Resource or nil # @param [block] &block to be stored for later calls when base_or_resource is nil @@ -51,13 +145,13 @@ else # backwards compatibility @treebase end end end - + # if called without parameter or block the given dn_prefix gets returned. - # if called with a block then the block gets stored. if called with a + # if called with a block then the block gets stored. if called with a # String then it gets stored. if called with a Resource then either the # stored block gets called with that Resource or the stored String gets # returned. # @param [String,DataMapper::Resource] prefix_or_resource either a String, a Resource or nil # @param [&block] block to be stored for later calls @@ -73,37 +167,30 @@ end else @ldap_dn = block end end - - # if called without parameter then the stored field gets returned + + # if called without parameter then the stored field gets returned # otherwise the given parameters gets stored # @param [Symbol, String] field a new multivalue_field # @return [Symbol] the multivalue_field def multivalue_field(field = nil) if field.nil? @ldap_multivalue_field else @ldap_multivalue_field = field.to_sym end end - end - - # authenticate the current resource against the stored password - # @param [String] password to authenticate - # @return [TrueClass, FalseClass] whether password was right or wrong - def authenticate(password) - ldap.authenticate(ldap.dn(self.class.dn_prefix(self), - self.class.treebase), - password) - end - private - # short cut to the ldap facade - # @return [Ldap::LdapFacade] - def ldap - raise "not an ldap adapter #{repository.adapter.name}" unless repository.adapter.respond_to? :ldap - repository.adapter.ldap + private + # short cut to the ldap facade + # @return [Ldap::LdapFacade] + def ldap + raise "not an ldap adapter #{repository.adapter.name}" unless repository.adapter.respond_to? :ldap + repository.adapter.ldap + end end + + include LdapResource end end