inverse_of 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ == 0.1.0 2011-08-31
2
+
3
+ * Fix bug with eager loading.
4
+ * Require AR < 2.3.6.
5
+
6
+ == 0.0.1 2010-02-05
7
+
8
+ * Hi.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 George Ogata
1
+ Copyright (c) 2009-2010 George Ogata
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,38 +1 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "inverse_of"
8
- gem.summary = "Backport of ActiveRecord 2.3.6's inverse associations."
9
- gem.description = "Backport of ActiveRecord 2.3.6's inverse associations."
10
- gem.email = "george.ogata@gmail.com"
11
- gem.homepage = "http://github.com/oggy/inverse_of"
12
- gem.authors = ["George Ogata"]
13
- end
14
- Jeweler::GemcutterTasks.new
15
- rescue LoadError
16
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
- end
18
-
19
- require 'rake/testtask'
20
-
21
- desc "Run the test/unit tests for inverse associations, backported from ActiveRecord 2.3.6."
22
- Rake::TestTask.new(:test => :check_dependencies) do |test|
23
- test.libs << 'lib' << 'test'
24
- test.pattern = 'test/**/*_test.rb'
25
- test.verbose = true
26
- end
27
-
28
- task :default => :test
29
-
30
- require 'rake/rdoctask'
31
- Rake::RDocTask.new do |rdoc|
32
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
33
-
34
- rdoc.rdoc_dir = 'rdoc'
35
- rdoc.title = "inverse_of #{version}"
36
- rdoc.rdoc_files.include('README*')
37
- rdoc.rdoc_files.include('lib/**/*.rb')
38
- end
1
+ require 'ritual'
@@ -1,293 +1,292 @@
1
- if ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR, ActiveRecord::VERSION::TINY] <=> [2, 3, 6]) < 0
2
- module InverseOf
3
- class InverseOfAssociationNotFoundError < ActiveRecord::ActiveRecordError #:nodoc:
4
- def initialize(reflection, associated_class = nil)
5
- super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
6
- end
1
+ module InverseOf
2
+ class InverseOfAssociationNotFoundError < ActiveRecord::ActiveRecordError #:nodoc:
3
+ def initialize(reflection, associated_class = nil)
4
+ super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
5
+ end
6
+ end
7
+
8
+ module Reflection
9
+ def self.included(base)
10
+ base::AssociationReflection.send :include, AssociationReflection
11
+ base::ThroughReflection.send :include, ThroughReflection
7
12
  end
8
13
 
9
- module Reflection
14
+ module AssociationReflection
10
15
  def self.included(base)
11
- base::AssociationReflection.send :include, AssociationReflection
12
- base::ThroughReflection.send :include, ThroughReflection
16
+ base.alias_method_chain :check_validity!, :inverse_of
13
17
  end
14
18
 
15
- module AssociationReflection
16
- def self.included(base)
17
- base.alias_method_chain :check_validity!, :inverse_of
18
- end
19
-
20
- def check_validity_with_inverse_of!
21
- check_validity_of_inverse!
22
- check_validity_without_inverse_of!
23
- end
19
+ def check_validity_with_inverse_of!
20
+ check_validity_of_inverse!
21
+ check_validity_without_inverse_of!
22
+ end
24
23
 
25
- def check_validity_of_inverse!
26
- unless options[:polymorphic]
27
- if has_inverse? && inverse_of.nil?
28
- raise InverseOfAssociationNotFoundError.new(self)
29
- end
24
+ def check_validity_of_inverse!
25
+ unless options[:polymorphic]
26
+ if has_inverse? && inverse_of.nil?
27
+ raise InverseOfAssociationNotFoundError.new(self)
30
28
  end
31
29
  end
30
+ end
32
31
 
33
- def has_inverse?
34
- !@options[:inverse_of].nil?
35
- end
32
+ def has_inverse?
33
+ !@options[:inverse_of].nil?
34
+ end
36
35
 
37
- def inverse_of
38
- if has_inverse?
39
- @inverse_of ||= klass.reflect_on_association(options[:inverse_of])
40
- end
36
+ def inverse_of
37
+ if has_inverse?
38
+ @inverse_of ||= klass.reflect_on_association(options[:inverse_of])
41
39
  end
40
+ end
42
41
 
43
- def polymorphic_inverse_of(associated_class)
44
- if has_inverse?
45
- if inverse_relationship = associated_class.reflect_on_association(options[:inverse_of])
46
- inverse_relationship
47
- else
48
- raise InverseOfAssociationNotFoundError.new(self, associated_class)
49
- end
42
+ def polymorphic_inverse_of(associated_class)
43
+ if has_inverse?
44
+ if inverse_relationship = associated_class.reflect_on_association(options[:inverse_of])
45
+ inverse_relationship
46
+ else
47
+ raise InverseOfAssociationNotFoundError.new(self, associated_class)
50
48
  end
51
49
  end
52
50
  end
51
+ end
53
52
 
54
- module ThroughReflection
55
- def self.included(base)
56
- base.alias_method_chain :check_validity!, :inverse_of
57
- end
53
+ module ThroughReflection
54
+ def self.included(base)
55
+ base.alias_method_chain :check_validity!, :inverse_of
56
+ end
58
57
 
59
- def check_validity_with_inverse_of!
60
- check_validity_of_inverse!
61
- check_validity_without_inverse_of!
62
- end
58
+ def check_validity_with_inverse_of!
59
+ check_validity_of_inverse!
60
+ check_validity_without_inverse_of!
63
61
  end
64
62
  end
63
+ end
65
64
 
66
- module Associations
67
- module AssociationCollection
68
- def self.included(base)
69
- base.alias_method_chain :find_target, :inverse_of
70
- base.alias_method_chain :add_record_to_target_with_callbacks, :inverse_of
71
- end
72
-
73
- def find_target_with_inverse_of
74
- records = find_target_without_inverse_of
75
- records.each do |record|
76
- set_inverse_instance(record, @owner)
77
- end
78
- records
79
- end
65
+ module Associations
66
+ module AssociationCollection
67
+ def self.included(base)
68
+ base.alias_method_chain :find_target, :inverse_of
69
+ base.alias_method_chain :add_record_to_target_with_callbacks, :inverse_of
70
+ end
80
71
 
81
- def add_record_to_target_with_callbacks_with_inverse_of(record, &block)
82
- record = add_record_to_target_with_callbacks_without_inverse_of(record, &block)
72
+ def find_target_with_inverse_of
73
+ records = find_target_without_inverse_of
74
+ records.each do |record|
83
75
  set_inverse_instance(record, @owner)
84
- record
85
76
  end
77
+ records
86
78
  end
87
79
 
88
- module AssociationProxy
89
- def self.included(base)
90
- base.alias_method_chain :initialize, :inverse_of
91
- end
80
+ def add_record_to_target_with_callbacks_with_inverse_of(record, &block)
81
+ record = add_record_to_target_with_callbacks_without_inverse_of(record, &block)
82
+ set_inverse_instance(record, @owner)
83
+ record
84
+ end
85
+ end
92
86
 
93
- def initialize_with_inverse_of(owner, reflection)
94
- reflection.check_validity!
95
- initialize_without_inverse_of(owner, reflection)
96
- end
87
+ module AssociationProxy
88
+ def self.included(base)
89
+ base.alias_method_chain :initialize, :inverse_of
90
+ end
97
91
 
98
- private
92
+ def initialize_with_inverse_of(owner, reflection)
93
+ reflection.check_validity!
94
+ initialize_without_inverse_of(owner, reflection)
95
+ end
99
96
 
100
- def set_inverse_instance(record, instance)
101
- return if record.nil? || !we_can_set_the_inverse_on_this?(record)
102
- inverse_relationship = @reflection.inverse_of
103
- unless inverse_relationship.nil?
104
- record.send(:"set_#{inverse_relationship.name}_target", instance)
105
- end
106
- end
97
+ private
107
98
 
108
- # Override in subclasses
109
- def we_can_set_the_inverse_on_this?(record)
110
- false
99
+ def set_inverse_instance(record, instance)
100
+ return if record.nil? || !we_can_set_the_inverse_on_this?(record)
101
+ inverse_relationship = @reflection.inverse_of
102
+ unless inverse_relationship.nil?
103
+ record.send(:"set_#{inverse_relationship.name}_target", instance)
111
104
  end
112
105
  end
113
106
 
114
- module BelongsToAssociation
115
- def self.included(base)
116
- base.alias_method_chain :replace, :inverse_of
117
- base.alias_method_chain :find_target, :inverse_of
118
- end
107
+ # Override in subclasses
108
+ def we_can_set_the_inverse_on_this?(record)
109
+ false
110
+ end
111
+ end
119
112
 
120
- def replace_with_inverse_of(record)
121
- replace_without_inverse_of(record)
122
- set_inverse_instance(record, @owner)
123
- record
124
- end
113
+ module BelongsToAssociation
114
+ def self.included(base)
115
+ base.alias_method_chain :replace, :inverse_of
116
+ base.alias_method_chain :find_target, :inverse_of
117
+ end
125
118
 
126
- def find_target_with_inverse_of
127
- target = find_target_without_inverse_of and
128
- set_inverse_instance(target, @owner)
129
- target
130
- end
119
+ def replace_with_inverse_of(record)
120
+ replace_without_inverse_of(record)
121
+ set_inverse_instance(record, @owner)
122
+ record
123
+ end
131
124
 
132
- # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
133
- # has_one associations.
134
- def we_can_set_the_inverse_on_this?(record)
135
- @reflection.has_inverse? && @reflection.inverse_of.macro == :has_one
136
- end
125
+ def find_target_with_inverse_of
126
+ target = find_target_without_inverse_of and
127
+ set_inverse_instance(target, @owner)
128
+ target
137
129
  end
138
130
 
139
- module BelongsToPolymorphicAssociation
140
- def self.included(base)
141
- base.alias_method_chain :replace, :inverse_of
142
- base.alias_method_chain :find_target, :inverse_of
143
- end
131
+ # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
132
+ # has_one associations.
133
+ def we_can_set_the_inverse_on_this?(record)
134
+ @reflection.has_inverse? && @reflection.inverse_of.macro == :has_one
135
+ end
136
+ end
144
137
 
145
- def replace_with_inverse_of(record)
146
- replace_without_inverse_of(record)
147
- set_inverse_instance(record, @owner)
148
- record
149
- end
138
+ module BelongsToPolymorphicAssociation
139
+ def self.included(base)
140
+ base.alias_method_chain :replace, :inverse_of
141
+ base.alias_method_chain :find_target, :inverse_of
142
+ end
150
143
 
151
- def find_target_with_inverse_of
152
- target = find_target_without_inverse_of
153
- set_inverse_instance(target, @owner)
154
- target
155
- end
144
+ def replace_with_inverse_of(record)
145
+ replace_without_inverse_of(record)
146
+ set_inverse_instance(record, @owner)
147
+ record
148
+ end
156
149
 
157
- # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
158
- # has_one associations.
159
- def we_can_set_the_inverse_on_this?(record)
160
- if @reflection.has_inverse?
161
- inverse_association = @reflection.polymorphic_inverse_of(record.class)
162
- inverse_association && inverse_association.macro == :has_one
163
- else
164
- false
165
- end
166
- end
150
+ def find_target_with_inverse_of
151
+ target = find_target_without_inverse_of
152
+ set_inverse_instance(target, @owner)
153
+ target
154
+ end
167
155
 
168
- def set_inverse_instance(record, instance)
169
- return if record.nil? || !we_can_set_the_inverse_on_this?(record)
170
- inverse_relationship = @reflection.polymorphic_inverse_of(record.class)
171
- unless inverse_relationship.nil?
172
- record.send(:"set_#{inverse_relationship.name}_target", instance)
173
- end
156
+ # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
157
+ # has_one associations.
158
+ def we_can_set_the_inverse_on_this?(record)
159
+ if @reflection.has_inverse?
160
+ inverse_association = @reflection.polymorphic_inverse_of(record.class)
161
+ inverse_association && inverse_association.macro == :has_one
162
+ else
163
+ false
174
164
  end
175
165
  end
176
166
 
177
- module HasManyAssociation
178
- def we_can_set_the_inverse_on_this?(record)
179
- inverse = @reflection.inverse_of
180
- return !inverse.nil?
167
+ def set_inverse_instance(record, instance)
168
+ return if record.nil? || !we_can_set_the_inverse_on_this?(record)
169
+ inverse_relationship = @reflection.polymorphic_inverse_of(record.class)
170
+ unless inverse_relationship.nil?
171
+ record.send(:"set_#{inverse_relationship.name}_target", instance)
181
172
  end
182
173
  end
174
+ end
183
175
 
184
- module HasManyThroughAssociation
185
- def initialize(owner, reflection)
186
- super
187
- end
176
+ module HasManyAssociation
177
+ def we_can_set_the_inverse_on_this?(record)
178
+ inverse = @reflection.inverse_of
179
+ return !inverse.nil?
180
+ end
181
+ end
188
182
 
189
- # NOTE - not sure that we can actually cope with inverses here
190
- def we_can_set_the_inverse_on_this?(record)
191
- false
192
- end
183
+ module HasManyThroughAssociation
184
+ def initialize(owner, reflection)
185
+ super
193
186
  end
194
187
 
195
- module HasOneAssociation
196
- def self.included(base)
197
- base.alias_method_chain :find_target, :inverse_of
198
- base.alias_method_chain :new_record, :inverse_of
199
- base.alias_method_chain :replace, :inverse_of
200
- end
188
+ # NOTE - not sure that we can actually cope with inverses here
189
+ def we_can_set_the_inverse_on_this?(record)
190
+ false
191
+ end
192
+ end
201
193
 
202
- def find_target_with_inverse_of
203
- target = find_target_without_inverse_of
204
- set_inverse_instance(target, @owner)
205
- target
206
- end
194
+ module HasOneAssociation
195
+ def self.included(base)
196
+ base.alias_method_chain :find_target, :inverse_of
197
+ base.alias_method_chain :new_record, :inverse_of
198
+ base.alias_method_chain :replace, :inverse_of
199
+ end
207
200
 
208
- def replace_with_inverse_of(record, dont_save = false)
209
- value = replace_without_inverse_of(record, dont_save)
210
- set_inverse_instance(record, @owner)
211
- value
212
- end
201
+ def find_target_with_inverse_of
202
+ target = find_target_without_inverse_of
203
+ set_inverse_instance(target, @owner)
204
+ target
205
+ end
213
206
 
214
- private
207
+ def replace_with_inverse_of(record, dont_save = false)
208
+ value = replace_without_inverse_of(record, dont_save)
209
+ set_inverse_instance(record, @owner)
210
+ value
211
+ end
215
212
 
216
- def new_record_with_inverse_of(replace_existing, &block)
217
- record = new_record_without_inverse_of(replace_existing, &block)
218
- set_inverse_instance(record, @owner) unless replace_existing
219
- record
220
- end
213
+ private
221
214
 
222
- def we_can_set_the_inverse_on_this?(record)
223
- inverse = @reflection.inverse_of
224
- return !inverse.nil?
225
- end
215
+ def new_record_with_inverse_of(replace_existing, &block)
216
+ record = new_record_without_inverse_of(replace_existing, &block)
217
+ set_inverse_instance(record, @owner) unless replace_existing
218
+ record
226
219
  end
227
220
 
228
- module ClassMethods
229
- module JoinDependency
230
- def self.included(base)
231
- base.alias_method_chain :construct_association, :inverse_of
232
- end
221
+ def we_can_set_the_inverse_on_this?(record)
222
+ inverse = @reflection.inverse_of
223
+ return !inverse.nil?
224
+ end
225
+ end
233
226
 
234
- def construct_association_with_inverse_of(record, join, row)
235
- association = construct_association_without_inverse_of(record, join, row) or
236
- return nil
237
- association_proxy = record.send(join.reflection.name)
238
- association_proxy.__send__(:set_inverse_instance, association, record)
239
- end
227
+ module ClassMethods
228
+ module JoinDependency
229
+ def self.included(base)
230
+ base.alias_method_chain :construct_association, :inverse_of
231
+ end
232
+
233
+ def construct_association_with_inverse_of(record, join, row)
234
+ association = construct_association_without_inverse_of(record, join, row) or
235
+ return nil
236
+ association_proxy = record.send(join.reflection.name)
237
+ association_proxy.__send__(:set_inverse_instance, association, record)
238
+ return association
240
239
  end
241
240
  end
242
241
  end
242
+ end
243
243
 
244
- module AssociationPreload
245
- def self.included(base)
246
- base.extend ClassMethods
247
- base.metaclass.alias_method_chain :add_preloaded_records_to_collection, :inverse_of
248
- base.metaclass.alias_method_chain :set_association_single_records, :inverse_of
249
- end
244
+ module AssociationPreload
245
+ def self.included(base)
246
+ base.extend ClassMethods
247
+ base.metaclass.alias_method_chain :add_preloaded_records_to_collection, :inverse_of
248
+ base.metaclass.alias_method_chain :set_association_single_records, :inverse_of
249
+ end
250
250
 
251
- module ClassMethods
252
- def add_preloaded_records_to_collection_with_inverse_of(parent_records, reflection_name, associated_record)
253
- value = add_preloaded_records_to_collection_without_inverse_of(parent_records, reflection_name, associated_record)
254
- parent_records.each do |parent_record|
255
- association_proxy = parent_record.send(reflection_name)
256
- association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
257
- end
258
- value
251
+ module ClassMethods
252
+ def add_preloaded_records_to_collection_with_inverse_of(parent_records, reflection_name, associated_record)
253
+ value = add_preloaded_records_to_collection_without_inverse_of(parent_records, reflection_name, associated_record)
254
+ parent_records.each do |parent_record|
255
+ association_proxy = parent_record.send(reflection_name)
256
+ association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
259
257
  end
258
+ value
259
+ end
260
260
 
261
- def set_association_single_records_with_inverse_of(id_to_record_map, reflection_name, associated_records, key)
262
- value = set_association_single_records_without_inverse_of(id_to_record_map, reflection_name, associated_records, key)
263
- associated_records.each do |associated_record|
264
- mapped_records = id_to_record_map[associated_record[key].to_s]
265
- mapped_records.each do |mapped_record|
266
- association_proxy = mapped_record.send(reflection_name)
267
- association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record)
268
- end
261
+ def set_association_single_records_with_inverse_of(id_to_record_map, reflection_name, associated_records, key)
262
+ value = set_association_single_records_without_inverse_of(id_to_record_map, reflection_name, associated_records, key)
263
+ associated_records.each do |associated_record|
264
+ mapped_records = id_to_record_map[associated_record[key].to_s]
265
+ mapped_records.each do |mapped_record|
266
+ association_proxy = mapped_record.send(reflection_name)
267
+ association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record)
269
268
  end
270
- value
271
269
  end
270
+ value
272
271
  end
273
272
  end
274
273
  end
274
+ end
275
275
 
276
- ActiveRecord::InverseOfAssociationNotFoundError = InverseOf::InverseOfAssociationNotFoundError
277
- ActiveRecord::Associations::AssociationCollection.send :include, InverseOf::Associations::AssociationCollection
278
- ActiveRecord::Associations::AssociationProxy.send :include, InverseOf::Associations::AssociationProxy
279
- ActiveRecord::Associations::BelongsToAssociation.send :include, InverseOf::Associations::BelongsToAssociation
280
- ActiveRecord::Associations::BelongsToPolymorphicAssociation.send :include, InverseOf::Associations::BelongsToPolymorphicAssociation
281
- ActiveRecord::Associations::HasManyAssociation.send :include, InverseOf::Associations::HasManyAssociation
282
- ActiveRecord::Associations::HasManyThroughAssociation.send :include, InverseOf::Associations::HasManyThroughAssociation
283
- ActiveRecord::Associations::HasOneAssociation.send :include, InverseOf::Associations::HasOneAssociation
284
- ActiveRecord::Associations::ClassMethods::JoinDependency.send :include, InverseOf::Associations::ClassMethods::JoinDependency
285
- ActiveRecord::Reflection.send :include, InverseOf::Reflection
286
- ActiveRecord::Base.send :include, InverseOf::AssociationPreload
287
-
288
- module ActiveRecord::Associations::ClassMethods
289
- @@valid_keys_for_has_many_association << :inverse_of
290
- @@valid_keys_for_has_one_association << :inverse_of
291
- @@valid_keys_for_belongs_to_association << :inverse_of
292
- end
276
+ ActiveRecord::InverseOfAssociationNotFoundError = InverseOf::InverseOfAssociationNotFoundError
277
+ ActiveRecord::Associations::AssociationCollection.send :include, InverseOf::Associations::AssociationCollection
278
+ ActiveRecord::Associations::AssociationProxy.send :include, InverseOf::Associations::AssociationProxy
279
+ ActiveRecord::Associations::BelongsToAssociation.send :include, InverseOf::Associations::BelongsToAssociation
280
+ ActiveRecord::Associations::BelongsToPolymorphicAssociation.send :include, InverseOf::Associations::BelongsToPolymorphicAssociation
281
+ ActiveRecord::Associations::HasManyAssociation.send :include, InverseOf::Associations::HasManyAssociation
282
+ ActiveRecord::Associations::HasManyThroughAssociation.send :include, InverseOf::Associations::HasManyThroughAssociation
283
+ ActiveRecord::Associations::HasOneAssociation.send :include, InverseOf::Associations::HasOneAssociation
284
+ ActiveRecord::Associations::ClassMethods::JoinDependency.send :include, InverseOf::Associations::ClassMethods::JoinDependency
285
+ ActiveRecord::Reflection.send :include, InverseOf::Reflection
286
+ ActiveRecord::Base.send :include, InverseOf::AssociationPreload
287
+
288
+ module ActiveRecord::Associations::ClassMethods
289
+ @@valid_keys_for_has_many_association << :inverse_of
290
+ @@valid_keys_for_has_one_association << :inverse_of
291
+ @@valid_keys_for_belongs_to_association << :inverse_of
293
292
  end