mongoid_alize 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/config/locales/en.yml +10 -0
  2. data/lib/mongoid/alize/callback.rb +47 -3
  3. data/lib/mongoid/alize/callbacks/from/many.rb +6 -8
  4. data/lib/mongoid/alize/callbacks/from/one.rb +21 -9
  5. data/lib/mongoid/alize/callbacks/to/many_from_many.rb +2 -1
  6. data/lib/mongoid/alize/callbacks/to/many_from_one.rb +1 -1
  7. data/lib/mongoid/alize/callbacks/to/one_from_many.rb +1 -1
  8. data/lib/mongoid/alize/callbacks/to/one_from_one.rb +1 -1
  9. data/lib/mongoid/alize/errors/alize_error.rb +13 -0
  10. data/lib/mongoid/alize/errors/already_defined_field.rb +15 -0
  11. data/lib/mongoid/alize/errors/invalid_field.rb +15 -0
  12. data/lib/mongoid/alize/from_callback.rb +16 -3
  13. data/lib/mongoid/alize/to_callback.rb +29 -5
  14. data/lib/mongoid/alize/to_many_callback.rb +26 -21
  15. data/lib/mongoid/alize/to_one_callback.rb +2 -3
  16. data/lib/mongoid_alize.rb +6 -1
  17. data/spec/app/models/head.rb +4 -0
  18. data/spec/app/models/person.rb +3 -0
  19. data/spec/mongoid/alize/callback_spec.rb +46 -8
  20. data/spec/mongoid/alize/callbacks/from/many_spec.rb +92 -18
  21. data/spec/mongoid/alize/callbacks/from/one_spec.rb +106 -23
  22. data/spec/mongoid/alize/callbacks/to/many_from_many_spec.rb +9 -16
  23. data/spec/mongoid/alize/callbacks/to/many_from_one_spec.rb +8 -15
  24. data/spec/mongoid/alize/callbacks/to/one_from_many_spec.rb +14 -17
  25. data/spec/mongoid/alize/callbacks/to/one_from_one_spec.rb +12 -15
  26. data/spec/mongoid/alize/from_callback_spec.rb +44 -0
  27. data/spec/mongoid/alize/to_callback_spec.rb +74 -0
  28. data/spec/mongoid_alize_spec.rb +152 -16
  29. data/spec/spec_helper.rb +6 -0
  30. metadata +27 -21
@@ -6,16 +6,17 @@ describe Mongoid::Alize::Callbacks::To::ManyFromOne do
6
6
  end
7
7
 
8
8
  def args
9
- [Person, :seen_by, [:name, :created_at]]
9
+ [Person, :seen_by, [:name, :location, :created_at]]
10
10
  end
11
11
 
12
- def new_unit
12
+ def new_callback
13
13
  klass.new(*args)
14
14
  end
15
15
 
16
16
  def sees_fields
17
17
  { "_id" => @person.id,
18
18
  "name"=> "Bob",
19
+ "location" => "Paris",
19
20
  "created_at"=> @now.to_s(:utc) }
20
21
  end
21
22
 
@@ -32,20 +33,16 @@ describe Mongoid::Alize::Callbacks::To::ManyFromOne do
32
33
  :sees => [@person = Person.create(:name => "Bob",
33
34
  :created_at => @now = Time.now)])
34
35
  @person.seen_by = @head
35
- @unit = new_unit
36
+ @callback = new_callback
36
37
  end
37
38
 
38
39
  describe "#define_callback" do
39
40
  before do
40
- @unit.send(:define_callback)
41
+ @callback.send(:define_callback)
41
42
  end
42
43
 
43
44
  def run_callback
44
- @person.send(callback_name)
45
- end
46
-
47
- def callback_name
48
- "denormalize_to_seen_by"
45
+ @person.send(:_denormalize_to_seen_by)
49
46
  end
50
47
 
51
48
  it "should push the fields to the relation" do
@@ -75,15 +72,11 @@ describe Mongoid::Alize::Callbacks::To::ManyFromOne do
75
72
 
76
73
  describe "#define_destroy_callback" do
77
74
  before do
78
- @unit.send(:define_destroy_callback)
75
+ @callback.send(:define_destroy_callback)
79
76
  end
80
77
 
81
78
  def run_destroy_callback
82
- @person.send(destroy_callback_name)
83
- end
84
-
85
- def destroy_callback_name
86
- "denormalize_destroy_to_seen_by"
79
+ @person.send(:_denormalize_destroy_to_seen_by)
87
80
  end
88
81
 
89
82
  it "should pull first any existing array entries matching the _id" do
@@ -6,16 +6,17 @@ describe Mongoid::Alize::Callbacks::To::OneFromMany do
6
6
  end
7
7
 
8
8
  def args
9
- [Person, :heads, [:name, :created_at]]
9
+ [Person, :heads, [:name, :location, :created_at]]
10
10
  end
11
11
 
12
- def new_unit
12
+ def new_callback
13
13
  klass.new(*args)
14
14
  end
15
15
 
16
16
  before do
17
17
  Head.class_eval do
18
18
  field :captor_name, :type => String
19
+ field :captor_location, :type => String
19
20
  field :captor_created_at, :type => Time
20
21
  end
21
22
 
@@ -24,49 +25,45 @@ describe Mongoid::Alize::Callbacks::To::OneFromMany do
24
25
  :created_at => @now = Time.now))
25
26
  @person.heads = [@head]
26
27
 
27
- @unit = new_unit
28
+ @callback = new_callback
28
29
  end
29
30
 
30
31
  describe "#define_callback" do
31
32
  before do
32
- @unit.send(:define_callback)
33
+ @callback.send(:define_callback)
33
34
  end
34
35
 
35
36
  def run_callback
36
- @person.send(callback_name)
37
- end
38
-
39
- def callback_name
40
- "denormalize_to_heads"
37
+ @person.send(:_denormalize_to_heads)
41
38
  end
42
39
 
43
40
  it "should push the fields to the relation" do
44
41
  @head.captor_name.should be_nil
42
+ @head.captor_location.should be_nil
45
43
  @head.captor_created_at.should be_nil
46
44
  run_callback
47
45
  @head.captor_name.should == "Bob"
46
+ @head.captor_location.should == "Paris"
48
47
  @head.captor_created_at.to_i.should == @now.to_i
49
48
  end
50
49
  end
51
50
 
52
51
  describe "#define_destroy_callback" do
53
52
  def run_destroy_callback
54
- @person.send(destroy_callback_name)
55
- end
56
-
57
- def destroy_callback_name
58
- "denormalize_destroy_to_heads"
53
+ @person.send(:_denormalize_destroy_to_heads)
59
54
  end
60
55
 
61
56
  before do
62
- @unit.send(:define_destroy_callback)
57
+ @callback.send(:define_destroy_callback)
63
58
  end
64
59
 
65
60
  it "should remove the fields from the relation" do
66
- @head.captor_name.should be_nil
67
- @head.captor_created_at.should be_nil
61
+ @head.captor_name = "Chuck"
62
+ @head.captor_location = "Paris"
63
+ @head.captor_created_at = Time.now
68
64
  run_destroy_callback
69
65
  @head.captor_name.should be_nil
66
+ @head.captor_location.should be_nil
70
67
  @head.captor_created_at.should be_nil
71
68
  end
72
69
  end
@@ -6,16 +6,17 @@ describe Mongoid::Alize::Callbacks::To::OneFromOne do
6
6
  end
7
7
 
8
8
  def args
9
- [Person, :head, [:name, :created_at]]
9
+ [Person, :head, [:name, :location, :created_at]]
10
10
  end
11
11
 
12
- def new_unit
12
+ def new_callback
13
13
  klass.new(*args)
14
14
  end
15
15
 
16
16
  before do
17
17
  Head.class_eval do
18
18
  field :person_name, :type => String
19
+ field :person_location, :type => String
19
20
  field :person_created_at, :type => Time
20
21
  end
21
22
 
@@ -23,27 +24,25 @@ describe Mongoid::Alize::Callbacks::To::OneFromOne do
23
24
  :person => @person = Person.create(:name => "Bob",
24
25
  :created_at => @now = Time.now))
25
26
 
26
- @unit = new_unit
27
+ @callback = new_callback
27
28
  end
28
29
 
29
30
  describe "define_callback" do
30
31
  before do
31
- @unit.send(:define_callback)
32
+ @callback.send(:define_callback)
32
33
  end
33
34
 
34
35
  def run_callback
35
- @person.send(callback_name)
36
- end
37
-
38
- def callback_name
39
- "denormalize_to_head"
36
+ @person.send(:_denormalize_to_head)
40
37
  end
41
38
 
42
39
  it "should push the fields to the relation" do
43
40
  @head.person_name.should be_nil
41
+ @head.person_location.should be_nil
44
42
  @head.person_created_at.should be_nil
45
43
  run_callback
46
44
  @head.person_name.should == "Bob"
45
+ @head.person_location.should == "Paris"
47
46
  @head.person_created_at.to_i.should == @now.to_i
48
47
  end
49
48
 
@@ -55,22 +54,20 @@ describe Mongoid::Alize::Callbacks::To::OneFromOne do
55
54
 
56
55
  describe "define_destroy_callback" do
57
56
  before do
58
- @unit.send(:define_destroy_callback)
57
+ @callback.send(:define_destroy_callback)
59
58
  end
60
59
 
61
60
  def run_destroy_callback
62
- @person.send(destroy_callback_name)
63
- end
64
-
65
- def destroy_callback_name
66
- "denormalize_destroy_to_head"
61
+ @person.send(:_denormalize_destroy_to_head)
67
62
  end
68
63
 
69
64
  it "should nillify the fields in the relation" do
70
65
  @head.person_name = "Chuck"
66
+ @head.person_location = "Paris"
71
67
  @head.person_created_at = Time.now
72
68
  run_destroy_callback
73
69
  @head.person_name.should be_nil
70
+ @head.person_location.should be_nil
74
71
  @head.person_created_at.should be_nil
75
72
  end
76
73
 
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ class Mongoid::Alize::SpecFromCallback < Mongoid::Alize::FromCallback
4
+ def define_fields
5
+ end
6
+
7
+ def define_callback
8
+ klass.class_eval <<-CALLBACK
9
+ def _denormalize_from_person
10
+ end
11
+ CALLBACK
12
+ end
13
+ end
14
+
15
+ describe Mongoid::Alize::FromCallback do
16
+ def klass
17
+ Mongoid::Alize::SpecFromCallback
18
+ end
19
+
20
+ def args
21
+ [Head, :person, [:name, :location, :created_at]]
22
+ end
23
+
24
+ def new_callback
25
+ klass.new(*args)
26
+ end
27
+
28
+ before do
29
+ @callback = new_callback
30
+ end
31
+
32
+ describe "#set_callback" do
33
+ it "should set a callback on the klass" do
34
+ mock(@callback.klass).set_callback(:save, :before, "denormalize_from_person")
35
+ @callback.send(:set_callback)
36
+ end
37
+
38
+ it "should not set the callback if it's already set" do
39
+ @callback.send(:attach)
40
+ dont_allow(@callback.klass).set_callback
41
+ @callback.send(:set_callback)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ class Mongoid::Alize::SpecToCallback < Mongoid::Alize::ToCallback
4
+ def define_callback
5
+ klass.class_eval <<-CALLBACK
6
+ def _denormalize_to_head
7
+ end
8
+ CALLBACK
9
+ end
10
+
11
+ def define_destroy_callback
12
+ klass.class_eval <<-CALLBACK
13
+ def _denormalize_destroy_to_head
14
+ end
15
+ CALLBACK
16
+ end
17
+ end
18
+
19
+ describe Mongoid::Alize::ToCallback do
20
+ def klass
21
+ Mongoid::Alize::SpecToCallback
22
+ end
23
+
24
+ def args
25
+ [Person, :head, [:name, :location, :created_at]]
26
+ end
27
+
28
+ def new_callback
29
+ klass.new(*args)
30
+ end
31
+
32
+ before do
33
+ @callback = new_callback
34
+ end
35
+
36
+ describe "#set_callback" do
37
+ it "should set a callback on the klass" do
38
+ mock(@callback.klass).set_callback(:save, :after, "denormalize_to_head")
39
+ @callback.send(:set_callback)
40
+ end
41
+
42
+ it "should not set the callback if it's already set" do
43
+ @callback.send(:attach)
44
+ dont_allow(@callback.klass).set_callback
45
+ @callback.send(:set_callback)
46
+ end
47
+ end
48
+
49
+ describe "#set_destroy_callback" do
50
+ it "should set a destroy callback on the klass" do
51
+ mock(@callback.klass).set_callback(:destroy, :after, "denormalize_destroy_to_head")
52
+ @callback.send(:set_destroy_callback)
53
+ end
54
+
55
+ it "should not set the destroy callback if it's already set" do
56
+ @callback.send(:attach)
57
+ dont_allow(@callback.klass).set_callback
58
+ @callback.send(:set_destroy_callback)
59
+ end
60
+ end
61
+
62
+ describe "#alias_destroy_callback" do
63
+ it "should alias the destroy callback on the klass" do
64
+ mock(@callback.klass).alias_method("denormalize_destroy_to_head", "_denormalize_destroy_to_head")
65
+ @callback.send(:alias_destroy_callback)
66
+ end
67
+
68
+ it "should not alias the destroy callback if it's already set" do
69
+ @callback.send(:attach)
70
+ dont_allow(@callback.klass).alias_method
71
+ @callback.send(:alias_destroy_callback)
72
+ end
73
+ end
74
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Mongoid::Alize do
4
4
  def person_fields
5
- [:name]
5
+ [:name, :location]
6
6
  end
7
7
 
8
8
  def head_fields
@@ -10,8 +10,10 @@ describe Mongoid::Alize do
10
10
  end
11
11
 
12
12
  before do
13
- @head = Head.new(:size => @size = 10)
14
- @person = Person.new(:name => @name = "Bob")
13
+ @now = Time.now
14
+ stub(Time).now { @now }
15
+ @head = Head.new(:size => @size = 10, created_at: @now)
16
+ @person = Person.new(:name => @name = "Bob", created_at: @now)
15
17
  end
16
18
 
17
19
  describe "one-to-one" do
@@ -23,14 +25,29 @@ describe Mongoid::Alize do
23
25
 
24
26
  def assert_head
25
27
  @head.person_name.should == @name
28
+ @head.person_location.should == "Paris"
26
29
  end
27
30
 
28
- it "should pull attributes from person" do
31
+ it "should pull data from person on create" do
29
32
  @head.save!
30
33
  assert_head
31
34
  end
32
35
 
33
- it "should push attributes to head" do
36
+ it "should pull data from a changed person on save" do
37
+ @head.save!
38
+ @head.person = Person.create(:name => @name = "Bill")
39
+ @head.save!
40
+ assert_head
41
+ end
42
+
43
+ it "should not pull data from an unchanged person on save" do
44
+ @head.save!
45
+ @head.person_name = "Cowboy"
46
+ @head.save!
47
+ @head.person_name.should == "Cowboy"
48
+ end
49
+
50
+ it "should push data to head" do
34
51
  @person.update_attributes!(:name => @name = "Bill")
35
52
  assert_head
36
53
  end
@@ -39,6 +56,7 @@ describe Mongoid::Alize do
39
56
  @head.update_attributes!(:person_name => "Old Gregg")
40
57
  @person.destroy
41
58
  @head.person_name.should be_nil
59
+ @head.person_location.should be_nil
42
60
  end
43
61
  end
44
62
 
@@ -52,12 +70,19 @@ describe Mongoid::Alize do
52
70
  @person.head_size.should == @size
53
71
  end
54
72
 
55
- it "should pull attributes from head" do
73
+ it "should pull data from head on create" do
56
74
  @person.save!
57
75
  assert_person
58
76
  end
59
77
 
60
- it "should push attributes to person" do
78
+ it "should pull data from head on save" do
79
+ @person.save!
80
+ @person.head = Head.create(:size => @size = 18)
81
+ @person.save!
82
+ assert_person
83
+ end
84
+
85
+ it "should push data to person" do
61
86
  @head.update_attributes!(:size => @size = "20lbs")
62
87
  assert_person
63
88
  end
@@ -81,17 +106,24 @@ describe Mongoid::Alize do
81
106
  @head.captor_name.should == @name
82
107
  end
83
108
 
84
- it "should pull attributes from head" do
109
+ it "should pull data from captor on create" do
85
110
  @head.save!
86
111
  assert_captor
87
112
  end
88
113
 
89
- it "should push attributes to person" do
114
+ it "should pull data from captor on save" do
115
+ @head.save!
116
+ @head.captor = Person.create(:name => @name = "Bill")
117
+ @head.save!
118
+ assert_captor
119
+ end
120
+
121
+ it "should push data to person" do
90
122
  @person.update_attributes!(:name => @name = "Bill")
91
123
  assert_captor
92
124
  end
93
125
 
94
- it "should nillify captor fieds when person is destroyed" do
126
+ it "should nillify captor fields when person is destroyed" do
95
127
  @head.update_attributes!(:captor_name => "Old Gregg")
96
128
  @person.destroy
97
129
  @head.captor_name.should be_nil
@@ -107,15 +139,23 @@ describe Mongoid::Alize do
107
139
  def assert_sees
108
140
  @head.sees_fields.should == [{
109
141
  "_id" => @person.id,
142
+ "location" => "Paris",
110
143
  "name" => @name }]
111
144
  end
112
145
 
113
- it "should pull attributes from sees" do
146
+ it "should pull data from sees on create" do
147
+ @head.save!
148
+ assert_sees
149
+ end
150
+
151
+ it "should pull data from a sees on save" do
152
+ @head.save!
153
+ @head.sees = [@person = Person.create(:name => @name = "Bill")]
114
154
  @head.save!
115
155
  assert_sees
116
156
  end
117
157
 
118
- it "should push attributes to seen_by" do
158
+ it "should push data to seen_by" do
119
159
  @person.update_attributes!(:name => @name = "Bill")
120
160
  assert_sees
121
161
  end
@@ -134,33 +174,129 @@ describe Mongoid::Alize do
134
174
  describe "has_and_belongs_to_many" do
135
175
  before do
136
176
  Head.send(:alize, :wanted_by, *person_fields)
137
- @head.wanted_by = [@person]
138
- @person.wants = [@head]
139
177
  end
140
178
 
141
179
  def assert_wanted_by
142
180
  @head.wanted_by_fields.should == [{
143
181
  "_id" => @person.id,
182
+ "location" => "Paris",
144
183
  "name" => @name }]
145
184
  end
146
185
 
147
- it "should pull attributes from wanted_by" do
186
+ it "should pull data from wanted_by on create" do
187
+ @head.wanted_by = [@person]
188
+ @head.save!
189
+ assert_wanted_by
190
+ end
191
+
192
+ it "should pull data from wanted_by on save" do
193
+ @head.save!
194
+ @person = Person.create(:name => @name = "Bill")
195
+ @head.wanted_by = [@person]
148
196
  @head.save!
149
197
  assert_wanted_by
150
198
  end
151
199
 
152
- it "should push attributes to wanted_by" do
200
+ it "should push data to wants" do
201
+ @person.wants = [@head]
153
202
  @person.update_attributes!(:name => @name = "Bill")
154
203
  assert_wanted_by
155
204
  end
156
205
 
157
206
  it "should remove wanted_by_fields entries in head when person is destroyed" do
207
+ @head.wanted_by = [@person]
158
208
  @head.save!
159
209
  assert_wanted_by
160
210
  @person.destroy
211
+ @head.reload
161
212
  @head.wanted_by_fields.should == []
162
213
  @head.reload.wanted_by_fields.should == []
163
214
  end
164
215
  end
165
216
  end
217
+
218
+ describe "without specifying fields" do
219
+ before do
220
+ Head.send(:alize, :person)
221
+ @head.person = @person
222
+ end
223
+
224
+ it "should denormalize all non-internal fields" do
225
+ @head.save!
226
+ @head.person_name.should == @name
227
+ @head.person_created_at.to_i.should == @now.to_i
228
+ end
229
+ end
230
+
231
+ describe "overriding denormalize methods for custom behavior on the from side" do
232
+ before do
233
+ class Person
234
+ def denormalize_update_name_first
235
+ self.name = "Overrider"
236
+ end
237
+ end
238
+
239
+ class Head
240
+ def denormalize_from_person
241
+ self.person.denormalize_update_name_first
242
+ _denormalize_from_person
243
+ end
244
+ end
245
+
246
+ Head.send(:alize, :person, *person_fields)
247
+ @head.person = @person
248
+ end
249
+
250
+ it "should be possible to define a method before alize and call the alize version within it" do
251
+ @head.save!
252
+ @head.person_name.should == "Overrider"
253
+ end
254
+ end
255
+
256
+ describe "overriding denormalize methods for custom behavior on the to side" do
257
+ before do
258
+ class Person
259
+ def denormalize_to_head
260
+ self.name = "Overrider"
261
+ _denormalize_to_head
262
+ end
263
+ end
264
+
265
+ Head.send(:alize, :person, *person_fields)
266
+ @head.person = @person
267
+ @head.save!
268
+ end
269
+
270
+ it "should be possible to define a method before alize and call the alize version within it" do
271
+ @person.update_attributes!(:name => @name = "Bill")
272
+ @head.person_name.should == "Overrider"
273
+ end
274
+ end
275
+
276
+ describe "forcing denormalization" do
277
+ before do
278
+ Head.send(:alize, :person, *person_fields)
279
+ @head.person = @person
280
+ @head.save!
281
+ end
282
+
283
+ it "should allow using the force flag to force denormalization" do
284
+ class Head
285
+ def denormalize_from_person
286
+ _denormalize_from_person(true)
287
+ end
288
+ end
289
+
290
+ @head.person_name = "Misty"
291
+ @head.save!
292
+ @head.person_name.should == @name
293
+ end
294
+
295
+ it "should allow using the force_denormalization attribute to force denormalization" do
296
+ @head.person_name = "Misty"
297
+ @head.force_denormalization = true
298
+ @head.save!
299
+ @head.person_name.should == @name
300
+ end
301
+ end
166
302
  end