active_mongoid 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +22 -0
- data/.ruby_gemset +1 -0
- data/.ruby_version +1 -0
- data/.travis.yml +11 -0
- data/Appraisals +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +198 -0
- data/Rakefile +7 -0
- data/active_mongoid.gemspec +36 -0
- data/gemfiles/mongoid_2.8.gemfile +7 -0
- data/gemfiles/mongoid_2.8.gemfile.lock +105 -0
- data/gemfiles/mongoid_3.1.gemfile +7 -0
- data/gemfiles/mongoid_3.1.gemfile.lock +108 -0
- data/lib/active_mongoid.rb +8 -0
- data/lib/active_mongoid/associations.rb +82 -0
- data/lib/active_mongoid/associations/binding.rb +77 -0
- data/lib/active_mongoid/associations/builder.rb +26 -0
- data/lib/active_mongoid/associations/builders/in.rb +17 -0
- data/lib/active_mongoid/associations/builders/many.rb +15 -0
- data/lib/active_mongoid/associations/builders/one.rb +15 -0
- data/lib/active_mongoid/associations/document_relation/accessors.rb +100 -0
- data/lib/active_mongoid/associations/document_relation/associations.rb +33 -0
- data/lib/active_mongoid/associations/document_relation/auto_save.rb +31 -0
- data/lib/active_mongoid/associations/document_relation/bindings/in.rb +48 -0
- data/lib/active_mongoid/associations/document_relation/bindings/many.rb +19 -0
- data/lib/active_mongoid/associations/document_relation/bindings/one.rb +19 -0
- data/lib/active_mongoid/associations/document_relation/builders.rb +31 -0
- data/lib/active_mongoid/associations/document_relation/dependent.rb +26 -0
- data/lib/active_mongoid/associations/document_relation/macros.rb +51 -0
- data/lib/active_mongoid/associations/document_relation/referenced/in.rb +72 -0
- data/lib/active_mongoid/associations/document_relation/referenced/many.rb +125 -0
- data/lib/active_mongoid/associations/document_relation/referenced/one.rb +75 -0
- data/lib/active_mongoid/associations/many.rb +211 -0
- data/lib/active_mongoid/associations/metadata.rb +229 -0
- data/lib/active_mongoid/associations/one.rb +21 -0
- data/lib/active_mongoid/associations/proxy.rb +38 -0
- data/lib/active_mongoid/associations/record_relation/accessors.rb +80 -0
- data/lib/active_mongoid/associations/record_relation/associations.rb +33 -0
- data/lib/active_mongoid/associations/record_relation/auto_save.rb +43 -0
- data/lib/active_mongoid/associations/record_relation/bindings/in.rb +48 -0
- data/lib/active_mongoid/associations/record_relation/bindings/many.rb +19 -0
- data/lib/active_mongoid/associations/record_relation/bindings/one.rb +19 -0
- data/lib/active_mongoid/associations/record_relation/builders.rb +31 -0
- data/lib/active_mongoid/associations/record_relation/dependent.rb +26 -0
- data/lib/active_mongoid/associations/record_relation/macros.rb +65 -0
- data/lib/active_mongoid/associations/record_relation/referenced/in.rb +72 -0
- data/lib/active_mongoid/associations/record_relation/referenced/many.rb +128 -0
- data/lib/active_mongoid/associations/record_relation/referenced/one.rb +75 -0
- data/lib/active_mongoid/associations/targets/enumerable.rb +161 -0
- data/lib/active_mongoid/bson_id.rb +44 -0
- data/lib/active_mongoid/finder_proxy.rb +55 -0
- data/lib/active_mongoid/finders.rb +60 -0
- data/lib/active_mongoid/version.rb +3 -0
- data/spec/lib/associations/document_relation/accessors_spec.rb +330 -0
- data/spec/lib/associations/document_relation/auto_save_spec.rb +157 -0
- data/spec/lib/associations/document_relation/bindings/in_spec.rb +39 -0
- data/spec/lib/associations/document_relation/bindings/many_spec.rb +36 -0
- data/spec/lib/associations/document_relation/bindings/one_spec.rb +39 -0
- data/spec/lib/associations/document_relation/builders_spec.rb +117 -0
- data/spec/lib/associations/document_relation/dependent_spec.rb +87 -0
- data/spec/lib/associations/document_relation/macros_spec.rb +68 -0
- data/spec/lib/associations/document_relation/referenced/in_spec.rb +27 -0
- data/spec/lib/associations/document_relation/referenced/many_spec.rb +32 -0
- data/spec/lib/associations/document_relation/referenced/one_spec.rb +28 -0
- data/spec/lib/associations/metadata_spec.rb +157 -0
- data/spec/lib/associations/record_relation/accessors_spec.rb +328 -0
- data/spec/lib/associations/record_relation/auto_save_spec.rb +157 -0
- data/spec/lib/associations/record_relation/bindings/in_spec.rb +39 -0
- data/spec/lib/associations/record_relation/bindings/many_spec.rb +39 -0
- data/spec/lib/associations/record_relation/bindings/one_spec.rb +57 -0
- data/spec/lib/associations/record_relation/builders_spec.rb +118 -0
- data/spec/lib/associations/record_relation/dependent_spec.rb +87 -0
- data/spec/lib/associations/record_relation/macros_spec.rb +73 -0
- data/spec/lib/associations/record_relation/referenced/in_spec.rb +27 -0
- data/spec/lib/associations/record_relation/referenced/many_spec.rb +32 -0
- data/spec/lib/associations/record_relation/referenced/one_spec.rb +27 -0
- data/spec/lib/bson_id_spec.rb +48 -0
- data/spec/lib/finders_spec.rb +105 -0
- data/spec/spec_helper.rb +89 -0
- data/spec/support/models/active_record/address.rb +6 -0
- data/spec/support/models/active_record/division.rb +16 -0
- data/spec/support/models/active_record/division_setting.rb +9 -0
- data/spec/support/models/active_record/player.rb +12 -0
- data/spec/support/models/mongoid/league.rb +10 -0
- data/spec/support/models/mongoid/person.rb +9 -0
- data/spec/support/models/mongoid/post.rb +9 -0
- data/spec/support/models/mongoid/stat.rb +8 -0
- data/spec/support/models/mongoid/team.rb +9 -0
- data/spec/support/shared_examples/shared_many_spec.rb +411 -0
- metadata +370 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module ActiveMongoid
|
|
2
|
+
module Associations
|
|
3
|
+
module DocumentRelation
|
|
4
|
+
module Referenced
|
|
5
|
+
class One < Associations::One
|
|
6
|
+
|
|
7
|
+
def initialize(base, target, metadata)
|
|
8
|
+
init(base, target, metadata) do
|
|
9
|
+
bind_one
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def substitute(replacement)
|
|
14
|
+
unbind_one
|
|
15
|
+
if base.persisted?
|
|
16
|
+
if __metadata__.destructive?
|
|
17
|
+
send(__metadata__.dependent)
|
|
18
|
+
else
|
|
19
|
+
save if persisted?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
One.new(base, replacement, __metadata__) if replacement
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def binding
|
|
28
|
+
Bindings::One.new(base, target, __metadata__)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
|
|
33
|
+
def stores_foreign_key?
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def foreign_key(name)
|
|
38
|
+
"#{name}#{foreign_key_suffix}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def foreign_key_default
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def foreign_key_suffix
|
|
46
|
+
"_id"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def primary_key_default
|
|
50
|
+
"id"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def macro
|
|
54
|
+
:has_one_document
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def builder(base, meta, object)
|
|
58
|
+
ActiveMongoid::Associations::Builders::One.new(base, meta, object)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def criteria(metadata, object, type = nil)
|
|
62
|
+
crit = metadata.klass.where(metadata.foreign_key => object)
|
|
63
|
+
if metadata.polymorphic?
|
|
64
|
+
crit = crit.where(metadata.type => type.name)
|
|
65
|
+
end
|
|
66
|
+
crit
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
module ActiveMongoid
|
|
2
|
+
module Associations
|
|
3
|
+
class Many < Proxy
|
|
4
|
+
include ::Mongoid::Threaded::Lifecycle
|
|
5
|
+
|
|
6
|
+
delegate :avg, :max, :min, :sum, to: :criteria
|
|
7
|
+
delegate :length, :size, to: :target
|
|
8
|
+
delegate :count, to: :criteria
|
|
9
|
+
delegate :first, :in_memory, :last, :reset, :uniq, to: :target
|
|
10
|
+
|
|
11
|
+
def initialize(base, target, metadata)
|
|
12
|
+
init(base, ActiveMongoid::Associations::Targets::Enumerable.new(target), metadata) do
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def <<(*args)
|
|
17
|
+
objs = args.flatten
|
|
18
|
+
return concat(objs) if objs.size > 1
|
|
19
|
+
if objs = objs.first
|
|
20
|
+
append(objs)
|
|
21
|
+
objs.save if base.persisted? && !_binding?
|
|
22
|
+
end
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
alias :push :<<
|
|
26
|
+
|
|
27
|
+
def build(attributes = {}, type = nil)
|
|
28
|
+
obj = (type || klass).new(attributes)
|
|
29
|
+
append(obj)
|
|
30
|
+
yield(obj) if block_given?
|
|
31
|
+
obj
|
|
32
|
+
end
|
|
33
|
+
alias :new :build
|
|
34
|
+
|
|
35
|
+
def concat(objects)
|
|
36
|
+
objs, inserts = [], []
|
|
37
|
+
objects.each do |obj|
|
|
38
|
+
next unless obj
|
|
39
|
+
append(obj)
|
|
40
|
+
save_or_delay(obj, objs, inserts) if base.persisted?
|
|
41
|
+
end
|
|
42
|
+
persist_delayed(objs, inserts)
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def purge
|
|
47
|
+
unless __metadata__.destructive?
|
|
48
|
+
nullify
|
|
49
|
+
else
|
|
50
|
+
after_remove_error = nil
|
|
51
|
+
criteria.delete_all
|
|
52
|
+
many = target.clear do |obj|
|
|
53
|
+
unbind_one(obj)
|
|
54
|
+
obj.destroyed = true if obj.respond_to?(:destroyed=)
|
|
55
|
+
end
|
|
56
|
+
many
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
alias :clear :purge
|
|
60
|
+
|
|
61
|
+
def delete(object)
|
|
62
|
+
target.delete(object) do |obj|
|
|
63
|
+
unbind_one(obj) if obj
|
|
64
|
+
cascade!(obj) if obj
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_all(conditions = nil)
|
|
69
|
+
remove_all(conditions, :delete_all)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def destroy_all(conditions = nil)
|
|
73
|
+
remove_all(conditions, :destroy_all)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def each
|
|
77
|
+
if block_given?
|
|
78
|
+
target.each { |obj| yield(obj) }
|
|
79
|
+
else
|
|
80
|
+
to_enum
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def exists?
|
|
85
|
+
criteria.exists?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def find(*args)
|
|
89
|
+
begin
|
|
90
|
+
matching = criteria.find(*args)
|
|
91
|
+
rescue Exception => e
|
|
92
|
+
end
|
|
93
|
+
Array(matching).each { |obj| target.push(obj) }
|
|
94
|
+
matching
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def nullify
|
|
98
|
+
criteria.update_all(__metadata__.foreign_key => nil)
|
|
99
|
+
target.clear do |obj|
|
|
100
|
+
unbind_one(obj)
|
|
101
|
+
obj.changed_attributes.delete(__metadata__.foreign_key)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
alias :nullify_all :nullify
|
|
105
|
+
|
|
106
|
+
def blank?
|
|
107
|
+
size == 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def create(attributes = nil, type = nil, &block)
|
|
111
|
+
if attributes.is_a?(::Array)
|
|
112
|
+
attributes.map { |attrs| create(attrs, type, &block) }
|
|
113
|
+
else
|
|
114
|
+
obj = build(attributes, type, &block)
|
|
115
|
+
base.persisted? ? obj.save : raise_unsaved(obj)
|
|
116
|
+
obj
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def create!(attributes = nil, type = nil, &block)
|
|
121
|
+
if attributes.is_a?(::Array)
|
|
122
|
+
attributes.map { |attrs| create!(attrs, type, &block) }
|
|
123
|
+
else
|
|
124
|
+
obj = build(attributes, type, &block)
|
|
125
|
+
base.persisted? ? obj.save! : raise_unsaved(obj)
|
|
126
|
+
obj
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def find_or_create_by(attrs = {}, type = nil, &block)
|
|
131
|
+
find_or(:create, attrs, type, &block)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def find_or_initialize_by(attrs = {}, type = nil, &block)
|
|
135
|
+
find_or(:build, attrs, type, &block)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def nil?
|
|
139
|
+
false
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def respond_to?(name, include_private = false)
|
|
143
|
+
[].respond_to?(name, include_private) ||
|
|
144
|
+
klass.respond_to?(name, include_private) || super
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def scoped
|
|
148
|
+
criteria
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def unscoped
|
|
152
|
+
criteria.unscoped
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def raise_unsaved(obj)
|
|
156
|
+
# raise new exception
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def substitute(replacement)
|
|
160
|
+
if replacement
|
|
161
|
+
new_objs, objs = replacement.compact, []
|
|
162
|
+
new_ids = new_objs.map { |obj| obj.id }
|
|
163
|
+
remove_not_in(new_ids)
|
|
164
|
+
new_objs.each do |obj|
|
|
165
|
+
objs.push(obj) if obj.send(__metadata__.foreign_key) != base.id
|
|
166
|
+
end
|
|
167
|
+
concat(objs)
|
|
168
|
+
else
|
|
169
|
+
purge
|
|
170
|
+
end
|
|
171
|
+
self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def unscoped
|
|
175
|
+
klass.unscoped.where(__metadata__.foreign_key => base.id)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def find_or(method, attrs = {}, type = nil, &block)
|
|
181
|
+
attrs["_type"] = type.to_s if type
|
|
182
|
+
where(attrs).first || send(method, attrs, type, &block)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def append(object)
|
|
186
|
+
target.push(object)
|
|
187
|
+
# characterize_one(object)
|
|
188
|
+
bind_one(object)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def cascade!(object)
|
|
192
|
+
if base.persisted?
|
|
193
|
+
if __metadata__.destructive?
|
|
194
|
+
object.send(__metadata__.dependent)
|
|
195
|
+
else
|
|
196
|
+
object.save
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def with_polymorphic_criterion(criteria, metadata, type = nil)
|
|
202
|
+
if metadata.polymorphic?
|
|
203
|
+
criteria.where(metadata.type => type.name)
|
|
204
|
+
else
|
|
205
|
+
criteria
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
module ActiveMongoid
|
|
2
|
+
module Associations
|
|
3
|
+
class Metadata < Hash
|
|
4
|
+
|
|
5
|
+
delegate :primary_key_default, :foreign_key_default, :stores_foreign_key?, :macro, to: :relation
|
|
6
|
+
|
|
7
|
+
def as
|
|
8
|
+
self[:as]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def as?
|
|
12
|
+
!!as
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(properties = {})
|
|
16
|
+
merge!(properties)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def autosave
|
|
20
|
+
self[:autosave]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def autosave?
|
|
24
|
+
!!autosave
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def builder(base, object)
|
|
28
|
+
relation.builder(base, self, object)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def order
|
|
32
|
+
self[:order]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def criteria(object, type = nil)
|
|
36
|
+
query = relation.criteria(self, object, type)
|
|
37
|
+
if order
|
|
38
|
+
query = query.respond_to?(:order_by) ? query.order_by(order) : query.order(order)
|
|
39
|
+
end
|
|
40
|
+
query
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def key
|
|
44
|
+
relation.stores_foreign_key? ? foreign_key : primary_key
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def foreign_key
|
|
48
|
+
@foreign_key ||= determine_foreign_key
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def foreign_key_setter
|
|
52
|
+
@foreign_key_setter ||= "#{foreign_key}="
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def type_setter
|
|
56
|
+
@type_setter ||= "#{type}="
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def determine_key
|
|
60
|
+
relation.stores_foreign_key? ? foreign_key : primary_key
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def primary_key
|
|
64
|
+
@primary_key ||= (self[:primary_key] || primary_key_default)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def determine_foreign_key
|
|
68
|
+
return self[:foreign_key].to_s if self[:foreign_key]
|
|
69
|
+
|
|
70
|
+
if relation.stores_foreign_key?
|
|
71
|
+
relation.foreign_key(name)
|
|
72
|
+
else
|
|
73
|
+
inverse_metadata.foreign_key
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def object_class
|
|
78
|
+
class_name.constantize
|
|
79
|
+
end
|
|
80
|
+
alias_method :klass, :object_class
|
|
81
|
+
|
|
82
|
+
def class_name
|
|
83
|
+
(self[:class_name] || name.to_s.singularize.titleize.delete(' ')).sub(/\A::/,"")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def name
|
|
87
|
+
self[:name].to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def object_name
|
|
91
|
+
name.to_s.singularize
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def plural_anme
|
|
95
|
+
name.to_s.pluralize
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def relation
|
|
99
|
+
self[:relation]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def inverse_klass
|
|
103
|
+
@inverse_klass ||= inverse_class_name.constantize if inverse_class_name
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def inverse_class_name
|
|
107
|
+
self[:as] || self[:inverse_class_name]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def inverses(other = nil)
|
|
111
|
+
if self[:polymorphic]
|
|
112
|
+
lookup_inverses(other)
|
|
113
|
+
else
|
|
114
|
+
@inverses ||= determine_inverses
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def polymorphic?
|
|
119
|
+
@polymorphic ||= (!!self[:as] || !!self[:polymorphic])
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def lookup_inverses(other)
|
|
123
|
+
return [ inverse_of ] if inverse_of
|
|
124
|
+
if other
|
|
125
|
+
matches = []
|
|
126
|
+
other.class.am_relations.values.each do |meta|
|
|
127
|
+
if meta.as.to_s == name && meta.class_name == inverse_class_name
|
|
128
|
+
matches.push(meta.name)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
matches
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def determine_inverse_for(field)
|
|
136
|
+
relation.stores_foreign_key? && polymorphic? ? "#{name}_#{field}" : nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def inverse_type
|
|
140
|
+
@inverse_type ||= determine_inverse_for(:type)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def inverse(other = nil)
|
|
144
|
+
invs = inverses(other)
|
|
145
|
+
invs.first if invs.count == 1
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def inverse_of
|
|
149
|
+
self[:inverse_of]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def inverse_setter(other = nil)
|
|
153
|
+
"#{inverse(other)}="
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def inverse_metadata(object = nil)
|
|
157
|
+
object = object || object_class
|
|
158
|
+
object.reflect_on_am_association(inverse(object))
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def determine_inverses
|
|
162
|
+
return [ inverse_of ] if has_key?(:inverse_of)
|
|
163
|
+
return [ as ] if has_key?(:as)
|
|
164
|
+
[ inverse_relation ]
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def inverse_relation
|
|
168
|
+
@inverse_relation ||= determine_inverse_relation
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def determine_inverse_relation
|
|
172
|
+
default = foreign_key_match || klass.am_relations[inverse_klass.name.underscore]
|
|
173
|
+
return default.name if default
|
|
174
|
+
klass.am_relations.each_pair do |key, meta|
|
|
175
|
+
next if meta.name == name
|
|
176
|
+
if meta.class_name == inverse_class_name
|
|
177
|
+
return key.to_sym
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
return nil
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def foreign_key_match
|
|
184
|
+
if fk = self[:foreign_key]
|
|
185
|
+
relations_metadata.detect do |meta|
|
|
186
|
+
fk == meta.foreign_key if meta.stores_foreign_key?
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def relations_metadata
|
|
192
|
+
klass.am_relations.values
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def dependent
|
|
196
|
+
self[:dependent]
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def destructive?
|
|
200
|
+
@destructive ||= (dependent == :delete || dependent == :destroy)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def polymorphic?
|
|
204
|
+
@polymorphic ||= (!!self[:as] || !!self[:polymorphic])
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def type
|
|
208
|
+
@type ||= polymorphic? ? "#{as}_type" : nil
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def type_setter
|
|
212
|
+
@type_setter ||= "#{type}="
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def determine_inverse_for(field)
|
|
216
|
+
relation.stores_foreign_key? && polymorphic? ? "#{name}_#{field}" : nil
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def inverse_type
|
|
220
|
+
@inverse_type ||= determine_inverse_for(:type)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def inverse_type_setter
|
|
224
|
+
@inverse_type_setter ||= "#{inverse_type}="
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|