Class: DataMapper::Associations::Relationship
- Includes:
- DataMapper::Assertions
- Defined in:
- lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb
Direct Known Subclasses
Constant Summary collapse
- OPTIONS =
[ :class_name, :child_key, :parent_key, :min, :max, :through ]
Instance Attribute Summary collapse
- #name ⇒ Object readonly private
- #options ⇒ Object readonly private
- #query ⇒ Object readonly private
Instance Method Summary collapse
- #attach_parent(child, parent) ⇒ Object private
- #child_key ⇒ Object private
- #child_model ⇒ Object private
- #get_children(parent, options = {}, finder = :all, *args) ⇒ Object private
- #get_parent(child, parent = nil) ⇒ Object private
- #parent_key ⇒ Object private
- #parent_model ⇒ Object private
- #with_repository(object = nil) ⇒ Object private
Methods included from DataMapper::Assertions
Instance Attribute Details
#name ⇒ Object (readonly)
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.
9 10 11 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 9 def name @name end |
#options ⇒ Object (readonly)
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.
9 10 11 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 9 def @options end |
#query ⇒ Object (readonly)
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.
9 10 11 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 9 def query @query end |
Instance Method Details
#attach_parent(child, parent) ⇒ Object
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.
177 178 179 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 177 def attach_parent(child, parent) child_key.set(child, parent && parent_key.get(parent)) end |
#child_key ⇒ Object
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.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 12 def child_key @child_key ||= begin child_key = nil child_model.repository.scope do |r| model_properties = child_model.properties(r.name) child_key = parent_key.zip(@child_properties || []).map do |parent_property,property_name| # TODO: use something similar to DM::NamingConventions to determine the property name parent_name = Extlib::Inflection.underscore(Extlib::Inflection.demodulize(parent_model.base_model.name)) property_name ||= "#{parent_name}_#{parent_property.name}".to_sym if model_properties.has_property?(property_name) model_properties[property_name] else = {} [ :length, :precision, :scale ].each do |option| [option] = parent_property.send(option) end # NOTE: hack to make each many to many child_key a true key, # until I can figure out a better place for this check if child_model.respond_to?(:many_to_many) [:key] = true end child_model.property(property_name, parent_property.primitive, ) end end end PropertySet.new(child_key) end end |
#child_model ⇒ Object
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.
69 70 71 72 73 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 69 def child_model Class === @child_model ? @child_model : (Class === @parent_model ? @parent_model.find_const(@child_model) : Object.find_const(@child_model)) rescue NameError raise NameError, "Cannot find the child_model #{@child_model} for #{@parent_model}" end |
#get_children(parent, options = {}, finder = :all, *args) ⇒ Object
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.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 76 def get_children(parent, = {}, finder = :all, *args) parent_value = parent_key.get(parent) bind_values = [ parent_value ] with_repository(child_model) do |r| parent_identity_map = parent.repository.identity_map(parent_model) child_identity_map = r.identity_map(child_model) query_values = parent_identity_map.keys query_values.reject! { |k| child_identity_map[k] } bind_values = query_values unless query_values.empty? query = child_key.zip(bind_values.transpose).to_hash collection = child_model.send(finder, *(args.dup << @query.merge().merge(query))) return collection unless collection.kind_of?(Collection) && collection.any? grouped_collection = {} collection.each do |resource| child_value = child_key.get(resource) parent_obj = parent_identity_map[child_value] grouped_collection[parent_obj] ||= [] grouped_collection[parent_obj] << resource end association_accessor = "#{self.name}_association" ret = nil grouped_collection.each do |parent, children| association = parent.send(association_accessor) query = collection.query.dup query.conditions.map! do |operator, property, bind_value| if operator != :raw && child_key.has_property?(property.name) bind_value = *children.map { |child| property.get(child) }.uniq end [ operator, property, bind_value ] end parents_children = Collection.new(query) children.each { |child| parents_children.send(:add, child) } if parent_key.get(parent) == parent_value ret = parents_children else association.instance_variable_set(:@children, parents_children) end end ret || child_model.send(finder, *(args.dup << @query.merge().merge(child_key.zip([ parent_value ]).to_hash))) end end |
#get_parent(child, parent = nil) ⇒ Object
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.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 131 def get_parent(child, parent = nil) child_value = child_key.get(child) return nil unless child_value.nitems == child_value.size with_repository(parent || parent_model) do parent_identity_map = (parent || parent_model).repository.identity_map(parent_model.base_model) child_identity_map = child.repository.identity_map(child_model.base_model) if parent = parent_identity_map[child_value] return parent end children = child_identity_map.values children << child unless child_identity_map[child.key] bind_values = children.map { |c| child_key.get(c) }.uniq query_values = bind_values.reject { |k| parent_identity_map[k] } bind_values = query_values unless query_values.empty? query = parent_key.zip(bind_values.transpose).to_hash association_accessor = "#{self.name}_association" collection = parent_model.send(:all, query) unless collection.empty? collection.send(:lazy_load) children.each do |c| c.send(association_accessor).instance_variable_set(:@parent, collection.get(*child_key.get(c))) end child.send(association_accessor).instance_variable_get(:@parent) end end end |
#parent_key ⇒ Object
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.
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 47 def parent_key @parent_key ||= begin parent_key = nil parent_model.repository.scope do |r| parent_key = if @parent_properties parent_model.properties(r.name).slice(*@parent_properties) else parent_model.key end end PropertySet.new(parent_key) end end |
#parent_model ⇒ Object
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.
62 63 64 65 66 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 62 def parent_model Class === @parent_model ? @parent_model : (Class === @child_model ? @child_model.find_const(@parent_model) : Object.find_const(@parent_model)) rescue NameError raise NameError, "Cannot find the parent_model #{@parent_model} for #{@child_model}" end |
#with_repository(object = nil) ⇒ Object
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.
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/gems/dm-core-0.9.9/lib/dm-core/associations/relationship.rb', line 165 def with_repository(object = nil) other_model = object.model == child_model ? parent_model : child_model if object.respond_to?(:model) other_model = object == child_model ? parent_model : child_model if object.kind_of?(DataMapper::Resource) if other_model && other_model.repository == object.repository && object.repository.name != @repository_name object.repository.scope { |block_args| yield(*block_args) } else repository(@repository_name) { |block_args| yield(*block_args) } end end |