Associations::Relationship
Relationship class with implementation specific to n side of 1 to n association
Initializes the relationship, always using max cardinality of 1.
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 202 202: def initialize(name, source_model, target_model, options = {}) 203: if options.key?(:nullable) 204: raise ":nullable is deprecated, use :required instead (#{caller[2]})" 205: end 206: 207: @required = options.fetch(:required, true) 208: @key = options.fetch(:key, false) 209: @unique = options.fetch(:unique, false) 210: target_model ||= DataMapper::Inflector.camelize(name) 211: options = { :min => @required ? 1 : 0, :max => 1 }.update(options) 212: super 213: end
Returns a set of keys that identify source model
@return [DataMapper::PropertySet] a set of properties that identify source model @api private
# File lib/dm-core/associations/many_to_one.rb, line 48 48: def child_key 49: return @child_key if defined?(@child_key) 50: 51: model = source_model 52: repository_name = source_repository_name || target_repository_name 53: properties = model.properties(repository_name) 54: 55: source_key = target_key.zip(@child_properties || []).map do |target_property, property_name| 56: property_name ||= "#{name}_#{target_property.name}".to_sym 57: 58: properties[property_name] || begin 59: # create the property within the correct repository 60: DataMapper.repository(repository_name) do 61: model.property(property_name, target_property.to_child_key, source_key_options(target_property)) 62: end 63: end 64: end 65: 66: @child_key = properties.class.new(source_key).freeze 67: end
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 165 165: def default_for(source) 166: typecast(super) 167: end
Initialize the foreign key property this “many to one” relationship uses to persist itself
@api public
# File lib/dm-core/associations/many_to_one.rb, line 76 76: def finalize 77: child_key 78: end
Loads and returns association target (ex.: author) for given source resource (ex.: article)
@param source [DataMapper::Resource]
source object (ex.: instance of article)
@param other_query [DataMapper::Query]
Query options
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 132 132: def get(source, query = nil) 133: lazy_load(source) 134: 135: if query 136: collection = get_collection(source) 137: collection.first(query) if collection 138: else 139: get!(source) 140: end 141: end
# File lib/dm-core/associations/many_to_one.rb, line 143 143: def get_collection(source) 144: target = get!(source) 145: target.collection_for_self if target 146: end
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 30 30: def key? 31: @key 32: end
Loads association target and sets resulting value on given source resource
@param [Resource] source
the source resource for the association
@return [undefined]
@api private
# File lib/dm-core/associations/many_to_one.rb, line 178 178: def lazy_load(source) 179: source_key_different = source_key_different?(source) 180: 181: if (loaded?(source) && !source_key_different) || !valid_source?(source) 182: return 183: end 184: 185: # SEL: load all related resources in the source collection 186: if source.saved? && (collection = source.collection).size > 1 187: eager_load(collection) 188: end 189: 190: if !loaded?(source) || (source_key_dirty?(source) && source.saved?) 191: set!(source, resource_for(source)) 192: elsif loaded?(source) && source_key_different 193: source_key.set(source, target_key.get!(get!(source))) 194: end 195: end
@deprecated
# File lib/dm-core/associations/many_to_one.rb, line 40 40: def nullable? 41: raise "#{self.class}#nullable? is deprecated, use #{self.class}#required? instead (#{caller.first})" 42: end
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 25 25: def required? 26: @required 27: end
Returns a Resource for this relationship with a given source
@param [Resource] source
A Resource to scope the collection with
@param [Query] other_query (optional)
A Query to further scope the collection with
@return [Resource]
The resource scoped to the relationship, source and query
@api private
# File lib/dm-core/associations/many_to_one.rb, line 106 106: def resource_for(source, other_query = nil) 107: query = query_for(source, other_query) 108: 109: # If the target key is equal to the model key, we can use the 110: # Model#get so the IdentityMap is used 111: if target_key == target_model.key 112: target = target_model.get(*source_key.get!(source)) 113: if query.conditions.matches?(target) 114: target 115: else 116: nil 117: end 118: else 119: target_model.first(query) 120: end 121: end
Sets value of association target (ex.: author) for given source resource (ex.: article)
@param source [DataMapper::Resource]
source object (ex.: instance of article)
@param target [DataMapper::Resource]
target object (ex.: instance of author)
@api semipublic
# File lib/dm-core/associations/many_to_one.rb, line 158 158: def set(source, target) 159: target = typecast(target) 160: source_key.set(source, target_key.get(target)) 161: set!(source, target) 162: end
Returns a hash of conditions that scopes query that fetches target object
@return [Hash]
Hash of conditions that scopes query
@api private
# File lib/dm-core/associations/many_to_one.rb, line 87 87: def source_scope(source) 88: if source.kind_of?(Resource) 89: Query.target_conditions(source, source_key, target_key) 90: else 91: super 92: end 93: end
@api private
# File lib/dm-core/associations/many_to_one.rb, line 280 280: def child_properties 281: source_key.map { |property| property.name } 282: end
Sets the association targets in the resource
@param [Resource] source
the source to set
@param [Array(Resource)] targets
the target resource for the association
@param [Query, Hash] query
not used
@return [undefined]
@api private
# File lib/dm-core/associations/many_to_one.rb, line 227 227: def eager_load_targets(source, targets, query) 228: set(source, targets.first) 229: end
Returns the inverse relationship class
@api private
# File lib/dm-core/associations/many_to_one.rb, line 243 243: def inverse_class 244: OneToMany::Relationship 245: end
Returns the inverse relationship name
@api private
# File lib/dm-core/associations/many_to_one.rb, line 250 250: def inverse_name 251: name = super 252: return name if name 253: 254: name = DataMapper::Inflector.demodulize(source_model.name) 255: name = DataMapper::Inflector.underscore(name) 256: name = DataMapper::Inflector.pluralize(name) 257: name.to_sym 258: end
@api private
# File lib/dm-core/associations/many_to_one.rb, line 285 285: def source_key_different?(source) 286: source_key.get!(source) != target_key.get!(get!(source)) 287: end
@api private
# File lib/dm-core/associations/many_to_one.rb, line 290 290: def source_key_dirty?(source) 291: source.dirty_attributes.keys.any? { |property| source_key.include?(property) } 292: end
@api private
# File lib/dm-core/associations/many_to_one.rb, line 261 261: def source_key_options(target_property) 262: options = DataMapper::Ext::Hash.only(target_property.options, :length, :precision, :scale).update( 263: :index => name, 264: :required => required?, 265: :key => key?, 266: :unique => @unique 267: ) 268: 269: if target_property.primitive == Integer 270: min = target_property.min 271: max = target_property.max 272: 273: options.update(:min => min, :max => max) if min && max 274: end 275: 276: options 277: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.