Class: DataMapper::Associations::ManyToOne::Relationship

Inherits:
Relationship
  • Object
show all
Defined in:
lib/dm-core/associations/many_to_one.rb

Overview

Relationship class with implementation specific to n side of 1 to n association

Constant Summary

OPTIONS =
superclass::OPTIONS.dup << :required << :key << :unique

Instance Attribute Summary

Attributes inherited from Relationship

#child_repository_name, #instance_variable_name, #max, #min, #name, #options, #parent_repository_name, #query, #reader_visibility, #writer_visibility

Instance Method Summary collapse

Methods inherited from Relationship

#==, #child_model, #child_model?, #child_model_name, #eager_load, #eql?, #field, #get!, #hash, #inverse, #loaded?, #parent_key, #parent_model, #parent_model?, #parent_model_name, #query_for, #relative_target_repository_name, #relative_target_repository_name_for, #set!, #valid?

Methods included from Subject

#default?

Methods included from DataMapper::Assertions

#assert_kind_of

Instance Method Details

#child_keyDataMapper::PropertySet Also known as: source_key

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a set of keys that identify source model



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/dm-core/associations/many_to_one.rb', line 48

def child_key
  return @child_key if defined?(@child_key)

  model           = source_model
  repository_name = source_repository_name || target_repository_name
  properties      = model.properties(repository_name)

  source_key = target_key.zip(@child_properties || []).map do |target_property, property_name|
    property_name ||= "#{name}_#{target_property.name}".to_sym

    properties[property_name] || begin
      # create the property within the correct repository
      DataMapper.repository(repository_name) do
        model.property(property_name, target_property.to_child_key, source_key_options(target_property))
      end
    end
  end

  @child_key = properties.class.new(source_key).freeze
end

#default_for(source) ⇒ Object



168
169
170
# File 'lib/dm-core/associations/many_to_one.rb', line 168

def default_for(source)
  typecast(super)
end

#finalizeself

Initialize the foreign key property this “many to one” relationship uses to persist itself



78
79
80
81
# File 'lib/dm-core/associations/many_to_one.rb', line 78

def finalize
  child_key
  self
end

#get(source, query = nil) ⇒ Object

Loads and returns association target (ex.: author) for given source resource (ex.: article)



135
136
137
138
139
140
141
142
143
144
# File 'lib/dm-core/associations/many_to_one.rb', line 135

def get(source, query = nil)
  lazy_load(source)

  if query
    collection = get_collection(source)
    collection.first(query) if collection
  else
    get!(source)
  end
end

#get_collection(source) ⇒ Object



146
147
148
149
# File 'lib/dm-core/associations/many_to_one.rb', line 146

def get_collection(source)
  target = get!(source)
  target.collection_for_self if target
end

#key?Boolean



30
31
32
# File 'lib/dm-core/associations/many_to_one.rb', line 30

def key?
  @key
end

#lazy_load(source) ⇒ undefined

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Loads association target and sets resulting value on given source resource



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/dm-core/associations/many_to_one.rb', line 181

def lazy_load(source)
  source_key_different = source_key_different?(source)

  if (loaded?(source) && !source_key_different) || !valid_source?(source)
    return
  end

  # SEL: load all related resources in the source collection
  if source.saved? && (collection = source.collection).size > 1
    eager_load(collection)
  end

  if !loaded?(source) || (source_key_dirty?(source) && source.saved?)
    set!(source, resource_for(source))
  elsif loaded?(source) && source_key_different
    source_key.set(source, target_key.get!(get!(source)))
  end
end

#nullable?Boolean

Deprecated.


40
41
42
# File 'lib/dm-core/associations/many_to_one.rb', line 40

def nullable?
  raise "#{self.class}#nullable? is deprecated, use #{self.class}#required? instead (#{caller.first})"
end

#required?Boolean



25
26
27
# File 'lib/dm-core/associations/many_to_one.rb', line 25

def required?
  @required
end

#resource_for(source, other_query = nil) ⇒ Resource

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a Resource for this relationship with a given source



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/dm-core/associations/many_to_one.rb', line 109

def resource_for(source, other_query = nil)
  query = query_for(source, other_query)

  # If the target key is equal to the model key, we can use the
  # Model#get so the IdentityMap is used
  if target_key == target_model.key
    target = target_model.get(*source_key.get!(source))
    if query.conditions.matches?(target)
      target
    else
      nil
    end
  else
    target_model.first(query)
  end
end

#set(source, target) ⇒ Object

Sets value of association target (ex.: author) for given source resource (ex.: article)



161
162
163
164
165
# File 'lib/dm-core/associations/many_to_one.rb', line 161

def set(source, target)
  target = typecast(target)
  source_key.set(source, target_key.get(target))
  set!(source, target)
end

#source_scope(source) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a hash of conditions that scopes query that fetches target object



90
91
92
93
94
95
96
# File 'lib/dm-core/associations/many_to_one.rb', line 90

def source_scope(source)
  if source.kind_of?(Resource)
    Query.target_conditions(source, source_key, target_key)
  else
    super
  end
end

#unique?Boolean



35
36
37
# File 'lib/dm-core/associations/many_to_one.rb', line 35

def unique?
  !!@unique
end