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