mongoid_alize 0.1.0 → 0.2.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.
- data/config/locales/en.yml +10 -0
- data/lib/mongoid/alize/callback.rb +47 -3
- data/lib/mongoid/alize/callbacks/from/many.rb +6 -8
- data/lib/mongoid/alize/callbacks/from/one.rb +21 -9
- data/lib/mongoid/alize/callbacks/to/many_from_many.rb +2 -1
- data/lib/mongoid/alize/callbacks/to/many_from_one.rb +1 -1
- data/lib/mongoid/alize/callbacks/to/one_from_many.rb +1 -1
- data/lib/mongoid/alize/callbacks/to/one_from_one.rb +1 -1
- data/lib/mongoid/alize/errors/alize_error.rb +13 -0
- data/lib/mongoid/alize/errors/already_defined_field.rb +15 -0
- data/lib/mongoid/alize/errors/invalid_field.rb +15 -0
- data/lib/mongoid/alize/from_callback.rb +16 -3
- data/lib/mongoid/alize/to_callback.rb +29 -5
- data/lib/mongoid/alize/to_many_callback.rb +26 -21
- data/lib/mongoid/alize/to_one_callback.rb +2 -3
- data/lib/mongoid_alize.rb +6 -1
- data/spec/app/models/head.rb +4 -0
- data/spec/app/models/person.rb +3 -0
- data/spec/mongoid/alize/callback_spec.rb +46 -8
- data/spec/mongoid/alize/callbacks/from/many_spec.rb +92 -18
- data/spec/mongoid/alize/callbacks/from/one_spec.rb +106 -23
- data/spec/mongoid/alize/callbacks/to/many_from_many_spec.rb +9 -16
- data/spec/mongoid/alize/callbacks/to/many_from_one_spec.rb +8 -15
- data/spec/mongoid/alize/callbacks/to/one_from_many_spec.rb +14 -17
- data/spec/mongoid/alize/callbacks/to/one_from_one_spec.rb +12 -15
- data/spec/mongoid/alize/from_callback_spec.rb +44 -0
- data/spec/mongoid/alize/to_callback_spec.rb +74 -0
- data/spec/mongoid_alize_spec.rb +152 -16
- data/spec/spec_helper.rb +6 -0
- metadata +27 -21
data/spec/app/models/head.rb
CHANGED
data/spec/app/models/person.rb
CHANGED
@@ -1,26 +1,64 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
class Mongoid::Alize::SpecCallback < Mongoid::Alize::Callback
|
4
|
+
def attach
|
5
|
+
klass.class_eval do
|
6
|
+
def denormalize_spec_person
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def direction
|
12
|
+
"spec"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
3
16
|
describe Mongoid::Alize::Callback do
|
4
17
|
def klass
|
5
|
-
Mongoid::Alize::
|
18
|
+
Mongoid::Alize::SpecCallback
|
6
19
|
end
|
7
20
|
|
8
21
|
def args
|
9
22
|
[Head, :person, [:name, :created_at]]
|
10
23
|
end
|
11
24
|
|
12
|
-
def
|
25
|
+
def new_callback
|
13
26
|
klass.new(*args)
|
14
27
|
end
|
15
28
|
|
16
29
|
describe "initialize" do
|
17
30
|
it "should assign class attributes" do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
31
|
+
callback = new_callback
|
32
|
+
callback.klass.should == Head
|
33
|
+
callback.relation.should == :person
|
34
|
+
callback.inverse_klass = Person
|
35
|
+
callback.inverse_relation = :head
|
36
|
+
callback.fields.should == [:name, :created_at]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should add force_denormalization attribute to klass and inverse klass" do
|
40
|
+
callback = new_callback
|
41
|
+
Head.new.force_denormalization = true
|
42
|
+
Person.new.force_denormalization = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "with callback " do
|
47
|
+
before do
|
48
|
+
@callback = new_callback
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#alias_callback" do
|
52
|
+
it "should alias the callback on the klass" do
|
53
|
+
mock(@callback.klass).alias_method("denormalize_spec_person", "_denormalize_spec_person")
|
54
|
+
@callback.send(:alias_callback)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not alias the callback if it's already set" do
|
58
|
+
@callback.send(:attach)
|
59
|
+
dont_allow(@callback.klass).alias_method
|
60
|
+
@callback.send(:alias_callback)
|
61
|
+
end
|
24
62
|
end
|
25
63
|
end
|
26
64
|
end
|
@@ -6,47 +6,121 @@ describe Mongoid::Alize::Callbacks::From::Many do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def args
|
9
|
-
[Head, :wanted_by, [:name, :created_at]]
|
9
|
+
[Head, :wanted_by, [:name, :location, :created_at]]
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def new_callback
|
13
13
|
klass.new(*args)
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "#define_fields" do
|
17
17
|
it "should define an Array called {relation}_fields" do
|
18
|
-
|
19
|
-
|
18
|
+
callback = new_callback
|
19
|
+
callback.send(:define_fields)
|
20
20
|
Head.fields["wanted_by_fields"].type.should == Array
|
21
21
|
end
|
22
|
+
|
23
|
+
it "should default the field to empty" do
|
24
|
+
callback = new_callback
|
25
|
+
callback.send(:define_fields)
|
26
|
+
Head.new.wanted_by_fields.should == []
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should raise an already defined field error if the field already exists" do
|
30
|
+
Head.class_eval do
|
31
|
+
field :wanted_by_fields
|
32
|
+
end
|
33
|
+
callback = new_callback
|
34
|
+
expect {
|
35
|
+
callback.send(:define_fields)
|
36
|
+
}.to raise_error(Mongoid::Alize::Errors::AlreadyDefinedField,
|
37
|
+
"wanted_by_fields is already defined on the Head model.")
|
38
|
+
end
|
22
39
|
end
|
23
40
|
|
24
41
|
describe "the defined callback" do
|
25
42
|
def run_callback
|
26
|
-
@head.send(
|
43
|
+
@head.send(:_denormalize_from_wanted_by)
|
44
|
+
end
|
45
|
+
|
46
|
+
def bob_fields
|
47
|
+
{ "_id" => @person.id,
|
48
|
+
"name"=> "Bob",
|
49
|
+
"location" => "Paris",
|
50
|
+
"created_at"=> @now.to_s(:utc) }
|
51
|
+
end
|
52
|
+
|
53
|
+
before do
|
54
|
+
now = Time.now
|
55
|
+
stub(Time).now { now }
|
56
|
+
@head = Head.create
|
57
|
+
@person = Person.create(:name => "Bob", :created_at => @now = Time.now)
|
58
|
+
|
59
|
+
@head.relations["wanted_by"].should be_stores_foreign_key
|
27
60
|
end
|
28
61
|
|
29
|
-
|
30
|
-
|
62
|
+
describe "valid fields" do
|
63
|
+
before do
|
64
|
+
@callback = new_callback
|
65
|
+
@callback.send(:define_fields)
|
66
|
+
@callback.send(:define_callback)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should set fields from a changed relation" do
|
70
|
+
@head.wanted_by_ids << @person.id
|
71
|
+
@head.should be_wanted_by_ids_changed
|
72
|
+
run_callback
|
73
|
+
@head.wanted_by_fields.should == [bob_fields]
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should still set fields there are no changes" do
|
77
|
+
@head.should_not be_wanted_by_ids_changed
|
78
|
+
mock.proxy(@head).wanted_by
|
79
|
+
run_callback
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "with a field that doesn't exist" do
|
84
|
+
before do
|
85
|
+
@callback = klass.new(Head, :wanted_by, [:notreal])
|
86
|
+
@callback.send(:define_fields)
|
87
|
+
@callback.send(:define_callback)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should raise a no method error" do
|
91
|
+
@head.wanted_by_ids << @person.id
|
92
|
+
@head.wanted_by_fields.should be_nil
|
93
|
+
expect {
|
94
|
+
run_callback
|
95
|
+
}.to raise_error NoMethodError
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "in a one to many case" do
|
101
|
+
def run_callback
|
102
|
+
@head.send(:_denormalize_from_sees)
|
31
103
|
end
|
32
104
|
|
33
105
|
before do
|
34
|
-
|
35
|
-
|
36
|
-
|
106
|
+
now = Time.now
|
107
|
+
stub(Time).now { now }
|
108
|
+
@head = Head.create
|
109
|
+
@person = Person.create(:name => "Bob")
|
37
110
|
|
38
|
-
@
|
39
|
-
@
|
40
|
-
@
|
111
|
+
@callback = klass.new(Head, :sees, [:name])
|
112
|
+
@callback.send(:define_fields)
|
113
|
+
@callback.send(:define_callback)
|
114
|
+
|
115
|
+
@head.relations["sees"].should_not be_stores_foreign_key
|
41
116
|
end
|
42
117
|
|
43
|
-
it "should
|
44
|
-
@head.
|
118
|
+
it "should field from a changed relation" do
|
119
|
+
@head.sees << @person
|
45
120
|
run_callback
|
46
|
-
@head.
|
121
|
+
@head.sees_fields.should == [{
|
47
122
|
"_id" => @person.id,
|
48
|
-
"name"=> "Bob"
|
49
|
-
"created_at"=> @now.to_s(:utc)
|
123
|
+
"name" => "Bob"
|
50
124
|
}]
|
51
125
|
end
|
52
126
|
end
|
@@ -6,55 +6,138 @@ describe Mongoid::Alize::Callbacks::From::One do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def args
|
9
|
-
[Head, :person, [:name, :created_at]]
|
9
|
+
[Head, :person, [:name, :location, :created_at]]
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def new_callback
|
13
13
|
klass.new(*args)
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "#define_fields" do
|
17
17
|
it "should add properly typed, prefixed fields from the relation" do
|
18
|
-
|
19
|
-
|
18
|
+
callback = klass.new(Head, :person, [:name, :created_at])
|
19
|
+
callback.send(:define_fields)
|
20
20
|
Head.fields["person_name"].type.should == String
|
21
21
|
Head.fields["person_created_at"].type.should == Time
|
22
22
|
end
|
23
|
-
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
it "should define as a string field that's not defined" do
|
25
|
+
callback = klass.new(Head, :person, [:location])
|
26
|
+
callback.send(:define_fields)
|
27
|
+
Head.fields["person_location"].type.should == String
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not add the field if the field already exists" do
|
31
|
+
Head.class_eval do
|
32
|
+
field :person_name
|
33
|
+
end
|
34
|
+
callback = klass.new(Head, :person, [:name])
|
35
|
+
dont_allow(Head).field
|
36
|
+
callback.send(:define_fields)
|
28
37
|
end
|
29
38
|
|
30
|
-
|
31
|
-
|
39
|
+
it "should not add the field if it already exists b/c of another relation" do
|
40
|
+
callback = klass.new(Head, :person, [:id])
|
41
|
+
dont_allow(Head).field
|
42
|
+
callback.send(:define_fields)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should allow the id and type of the inverse to be denormalized without an extra _" do
|
46
|
+
callback = klass.new(Person, :head, [:id, :type])
|
47
|
+
callback.send(:define_fields)
|
48
|
+
Person.fields["head_id"].type.should == BSON::ObjectId
|
49
|
+
Person.fields["head_type"].type.should == String
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "the defined callback" do
|
54
|
+
def run_callback(force=false)
|
55
|
+
@head.send(:_denormalize_from_person, force)
|
32
56
|
end
|
33
57
|
|
34
58
|
before do
|
35
|
-
@head = Head.create
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@
|
40
|
-
@
|
59
|
+
@head = Head.create
|
60
|
+
@person = Person.create(:name => @name = "Bob",
|
61
|
+
:created_at => @now = Time.now)
|
62
|
+
|
63
|
+
@callback = new_callback
|
64
|
+
@callback.send(:define_fields)
|
65
|
+
@callback.send(:define_callback)
|
66
|
+
|
67
|
+
@head.relations["person"].should be_stores_foreign_key
|
41
68
|
end
|
42
69
|
|
43
|
-
it "should set
|
44
|
-
@head.
|
45
|
-
@head.
|
70
|
+
it "should set fields from a changed relation" do
|
71
|
+
@head.person = @person
|
72
|
+
@head.should be_person_id_changed
|
46
73
|
run_callback
|
47
74
|
@head.person_name.should == @name
|
48
75
|
@head.person_created_at.to_i.should == @now.to_i
|
76
|
+
@head.person_location.should == "Paris"
|
49
77
|
end
|
50
78
|
|
51
|
-
it "should assign nil values if the relation is nil" do
|
52
|
-
@head.
|
53
|
-
@head.
|
79
|
+
it "should assign nil values if the changed relation is nil" do
|
80
|
+
@head.person = @person
|
81
|
+
@head.save!
|
54
82
|
@head.person = nil
|
83
|
+
@head.should be_person_id_changed
|
55
84
|
run_callback
|
56
85
|
@head.person_name.should be_nil
|
57
|
-
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should not run if the relation has not changed" do
|
89
|
+
@head.should_not be_person_id_changed
|
90
|
+
dont_allow(@head).person
|
91
|
+
run_callback
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should still run if the relation has not changed but force is passed" do
|
95
|
+
@head.should_not be_person_id_changed
|
96
|
+
mock.proxy(@head).person
|
97
|
+
run_callback(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should still run if the relation has not changed but force_denormalization is set on the class" do
|
101
|
+
@head.should_not be_person_id_changed
|
102
|
+
@head.force_denormalization = true
|
103
|
+
mock.proxy(@head).person
|
104
|
+
run_callback
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "the defined callback when denormalizing on the has_one side" do
|
109
|
+
def run_callback
|
110
|
+
@person.send(:_denormalize_from_head)
|
111
|
+
end
|
112
|
+
|
113
|
+
before do
|
114
|
+
@person = Person.create
|
115
|
+
@head = Head.create(:size => 5)
|
116
|
+
|
117
|
+
@callback = klass.new(Person, :head, [:size])
|
118
|
+
@callback.send(:define_fields)
|
119
|
+
@callback.send(:define_callback)
|
120
|
+
|
121
|
+
@person.relations["head"].should_not be_stores_foreign_key
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should set values from a changed relation" do
|
125
|
+
@person.head = @head
|
126
|
+
run_callback
|
127
|
+
@person.head_size.should == 5
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should set values from a a nil relation" do
|
131
|
+
@person.head = @head
|
132
|
+
@person.save!
|
133
|
+
@person.head = nil
|
134
|
+
run_callback
|
135
|
+
@person.head_size.should be_nil
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should run even if the relation has not changed" do
|
139
|
+
mock.proxy(@person).head
|
140
|
+
run_callback
|
58
141
|
end
|
59
142
|
end
|
60
143
|
end
|
@@ -6,16 +6,17 @@ describe Mongoid::Alize::Callbacks::To::ManyFromMany do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def args
|
9
|
-
[Person, :wants, [:name, :created_at]]
|
9
|
+
[Person, :wants, [:name, :location, :created_at]]
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def new_callback
|
13
13
|
klass.new(*args)
|
14
14
|
end
|
15
15
|
|
16
16
|
def wanted_by_fields
|
17
17
|
{ "_id" => @person.id,
|
18
|
-
"name"=> "Bob",
|
18
|
+
"name" => "Bob",
|
19
|
+
"location" => "Paris",
|
19
20
|
"created_at"=> @now.to_s(:utc) }
|
20
21
|
end
|
21
22
|
|
@@ -33,20 +34,16 @@ describe Mongoid::Alize::Callbacks::To::ManyFromMany do
|
|
33
34
|
:created_at => @now = Time.now)])
|
34
35
|
@person.wants = [@head]
|
35
36
|
|
36
|
-
@
|
37
|
+
@callback = new_callback
|
37
38
|
end
|
38
39
|
|
39
40
|
describe "#define_callback" do
|
40
41
|
before do
|
41
|
-
@
|
42
|
+
@callback.send(:define_callback)
|
42
43
|
end
|
43
44
|
|
44
45
|
def run_callback
|
45
|
-
@person.send(
|
46
|
-
end
|
47
|
-
|
48
|
-
def callback_name
|
49
|
-
"denormalize_to_wants"
|
46
|
+
@person.send(:_denormalize_to_wants)
|
50
47
|
end
|
51
48
|
|
52
49
|
it "should push the fields to the relation" do
|
@@ -71,15 +68,11 @@ describe Mongoid::Alize::Callbacks::To::ManyFromMany do
|
|
71
68
|
|
72
69
|
describe "#define_destroy_callback" do
|
73
70
|
before do
|
74
|
-
@
|
71
|
+
@callback.send(:define_destroy_callback)
|
75
72
|
end
|
76
73
|
|
77
74
|
def run_destroy_callback
|
78
|
-
@person.send(
|
79
|
-
end
|
80
|
-
|
81
|
-
def destroy_callback_name
|
82
|
-
"denormalize_destroy_to_wants"
|
75
|
+
@person.send(:_denormalize_destroy_to_wants)
|
83
76
|
end
|
84
77
|
|
85
78
|
it "should pull first any existing array entries matching the _id" do
|