mongoid_alize 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Alize::Callbacks::To::OneFromOne do
4
+ def klass
5
+ Mongoid::Alize::Callbacks::To::OneFromOne
6
+ end
7
+
8
+ def args
9
+ [Person, :head, [:name, :created_at]]
10
+ end
11
+
12
+ def new_unit
13
+ klass.new(*args)
14
+ end
15
+
16
+ before do
17
+ Head.class_eval do
18
+ field :person_name, :type => String
19
+ field :person_created_at, :type => Time
20
+ end
21
+
22
+ @head = Head.create(
23
+ :person => @person = Person.create(:name => "Bob",
24
+ :created_at => @now = Time.now))
25
+
26
+ @unit = new_unit
27
+ end
28
+
29
+ describe "define_callback" do
30
+ before do
31
+ @unit.send(:define_callback)
32
+ end
33
+
34
+ def run_callback
35
+ @person.send(callback_name)
36
+ end
37
+
38
+ def callback_name
39
+ "denormalize_to_head"
40
+ end
41
+
42
+ it "should push the fields to the relation" do
43
+ @head.person_name.should be_nil
44
+ @head.person_created_at.should be_nil
45
+ run_callback
46
+ @head.person_name.should == "Bob"
47
+ @head.person_created_at.to_i.should == @now.to_i
48
+ end
49
+
50
+ it "should do nothing if the relation doesn't exist" do
51
+ @head.person = nil
52
+ run_callback
53
+ end
54
+ end
55
+
56
+ describe "define_destroy_callback" do
57
+ before do
58
+ @unit.send(:define_destroy_callback)
59
+ end
60
+
61
+ def run_destroy_callback
62
+ @person.send(destroy_callback_name)
63
+ end
64
+
65
+ def destroy_callback_name
66
+ "denormalize_destroy_to_head"
67
+ end
68
+
69
+ it "should nillify the fields in the relation" do
70
+ @head.person_name = "Chuck"
71
+ @head.person_created_at = Time.now
72
+ run_destroy_callback
73
+ @head.person_name.should be_nil
74
+ @head.person_created_at.should be_nil
75
+ end
76
+
77
+ it "should do nothing if the relation doesn't exist" do
78
+ @head.person = nil
79
+ run_destroy_callback
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Alize::Macros do
4
+ describe "#alize" do
5
+ describe "with a belongs_to" do
6
+ it_should_set_callbacks(Head, Person,
7
+ :person, :head,
8
+ fns::One, tns::OneFromOne)
9
+ end
10
+
11
+ describe "with a has_one" do
12
+ it_should_set_callbacks(Person, Head,
13
+ :head, :person,
14
+ fns::One, tns::OneFromOne)
15
+ end
16
+
17
+ describe "with a has_many from the belongs_to side" do
18
+ it_should_set_callbacks(Head, Person,
19
+ :captor, :heads,
20
+ fns::One, tns::OneFromMany)
21
+ end
22
+
23
+ describe "with a has_many from the has_many side" do
24
+ it_should_set_callbacks(Head, Person,
25
+ :sees, :seen_by,
26
+ fns::Many, tns::ManyFromOne)
27
+ end
28
+
29
+ describe "with a has_and_belongs_to_many" do
30
+ it_should_set_callbacks(Head, Person,
31
+ :wanted_by, :wants,
32
+ fns::Many, tns::ManyFromMany)
33
+ end
34
+
35
+ describe "when no inverse is present" do
36
+ it "should add only a from and not a to callback" do
37
+ dont_allow(Mongoid::Alize::Callbacks::To::OneFromOne).new
38
+ Head.alize(:admirer)
39
+ end
40
+ end
41
+
42
+ describe "fields" do
43
+ describe "with fields supplied" do
44
+ it "should use them" do
45
+ dont_allow(Head).default_alize_fields
46
+ Head.alize(:person, :name)
47
+ end
48
+ end
49
+
50
+ describe "with no fields supplied" do
51
+ it "should use the default alize fields" do
52
+ mock(Head).default_alize_fields(:person) { [:name] }
53
+ Head.alize(:person)
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "default_alize_fields" do
59
+ it "should return an array of all non-internal field names (e.g. not _type or _id)" do
60
+ Head.default_alize_fields(:person).should ==
61
+ ["name", "created_at", "want_ids", "seen_by_id"]
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Alize do
4
+ def person_fields
5
+ [:name]
6
+ end
7
+
8
+ def head_fields
9
+ [:size]
10
+ end
11
+
12
+ before do
13
+ @head = Head.new(:size => @size = 10)
14
+ @person = Person.new(:name => @name = "Bob")
15
+ end
16
+
17
+ describe "one-to-one" do
18
+ describe "from belongs_to side" do
19
+ before do
20
+ Head.send(:alize, :person, *person_fields)
21
+ @head.person = @person
22
+ end
23
+
24
+ def assert_head
25
+ @head.person_name.should == @name
26
+ end
27
+
28
+ it "should pull attributes from person" do
29
+ @head.save!
30
+ assert_head
31
+ end
32
+
33
+ it "should push attributes to head" do
34
+ @person.update_attributes!(:name => @name = "Bill")
35
+ assert_head
36
+ end
37
+
38
+ it "should nillify person fields in head when person is destroyed" do
39
+ @head.update_attributes!(:person_name => "Old Gregg")
40
+ @person.destroy
41
+ @head.person_name.should be_nil
42
+ end
43
+ end
44
+
45
+ describe "from has_one side" do
46
+ before do
47
+ Person.send(:alize, :head, *head_fields)
48
+ @person.head = @head
49
+ end
50
+
51
+ def assert_person
52
+ @person.head_size.should == @size
53
+ end
54
+
55
+ it "should pull attributes from head" do
56
+ @person.save!
57
+ assert_person
58
+ end
59
+
60
+ it "should push attributes to person" do
61
+ @head.update_attributes!(:size => @size = "20lbs")
62
+ assert_person
63
+ end
64
+
65
+ it "should nillify head fields in person when head is destroyed" do
66
+ @person.update_attributes!(:head_size => "1000 balloons")
67
+ @head.destroy
68
+ @person.head_size.should be_nil
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "one-to-many" do
74
+ describe "from belongs_to side" do
75
+ before do
76
+ Head.send(:alize, :captor, *person_fields)
77
+ @head.captor = @person
78
+ end
79
+
80
+ def assert_captor
81
+ @head.captor_name.should == @name
82
+ end
83
+
84
+ it "should pull attributes from head" do
85
+ @head.save!
86
+ assert_captor
87
+ end
88
+
89
+ it "should push attributes to person" do
90
+ @person.update_attributes!(:name => @name = "Bill")
91
+ assert_captor
92
+ end
93
+
94
+ it "should nillify captor fieds when person is destroyed" do
95
+ @head.update_attributes!(:captor_name => "Old Gregg")
96
+ @person.destroy
97
+ @head.captor_name.should be_nil
98
+ end
99
+ end
100
+
101
+ describe "from has_many side" do
102
+ before do
103
+ Head.send(:alize, :sees, *person_fields)
104
+ @head.sees = [@person]
105
+ end
106
+
107
+ def assert_sees
108
+ @head.sees_fields.should == [{
109
+ "_id" => @person.id,
110
+ "name" => @name }]
111
+ end
112
+
113
+ it "should pull attributes from sees" do
114
+ @head.save!
115
+ assert_sees
116
+ end
117
+
118
+ it "should push attributes to seen_by" do
119
+ @person.update_attributes!(:name => @name = "Bill")
120
+ assert_sees
121
+ end
122
+
123
+ it "should remove sees_fields entries in head when person is destroyed" do
124
+ @head.save!
125
+ assert_sees
126
+ @person.destroy
127
+ @head.sees_fields.should == []
128
+ @head.reload.sees_fields.should == []
129
+ end
130
+ end
131
+ end
132
+
133
+ describe "many-to-many" do
134
+ describe "has_and_belongs_to_many" do
135
+ before do
136
+ Head.send(:alize, :wanted_by, *person_fields)
137
+ @head.wanted_by = [@person]
138
+ @person.wants = [@head]
139
+ end
140
+
141
+ def assert_wanted_by
142
+ @head.wanted_by_fields.should == [{
143
+ "_id" => @person.id,
144
+ "name" => @name }]
145
+ end
146
+
147
+ it "should pull attributes from wanted_by" do
148
+ @head.save!
149
+ assert_wanted_by
150
+ end
151
+
152
+ it "should push attributes to wanted_by" do
153
+ @person.update_attributes!(:name => @name = "Bill")
154
+ assert_wanted_by
155
+ end
156
+
157
+ it "should remove wanted_by_fields entries in head when person is destroyed" do
158
+ @head.save!
159
+ assert_wanted_by
160
+ @person.destroy
161
+ @head.wanted_by_fields.should == []
162
+ @head.reload.wanted_by_fields.should == []
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'looksee'
3
+ require 'awesome_print'
4
+ require 'wirble'
5
+ require 'mongoid'
6
+
7
+ Mongoid.configure do |config|
8
+ config.master = Mongo::Connection.new("localhost", 27017,
9
+ :logger => Logger.new("log/test.log")).db("mongoid_alize_test")
10
+ end
11
+
12
+ require File.expand_path("../../lib/mongoid_alize", __FILE__)
13
+ Dir["#{File.dirname(__FILE__)}/app/models/*.rb"].each { |f| require f }
14
+ Dir["#{File.dirname(__FILE__)}/helpers/*.rb"].each { |f| require f }
15
+
16
+ RSpec.configure do |config|
17
+ config.include(MacrosHelper)
18
+
19
+ config.mock_with :rr
20
+ config.before :each do
21
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
22
+
23
+ persistent_fields = {
24
+ Object => [:_id, :_type],
25
+ Person => [:name, :created_at, :want_ids, :seen_by_id],
26
+ Head => [:size, :weight, :person_id, :captor_id, :wanted_by_ids]
27
+ }
28
+
29
+ [Head, Person].each do |klass|
30
+ klass.reset_callbacks(:save)
31
+ klass.reset_callbacks(:create)
32
+ klass.fields.reject! do |field, value|
33
+ !(persistent_fields[klass] +
34
+ persistent_fields[Object]).include?(field.to_sym)
35
+ end
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid_alize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Josh Dzielak
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mongoid
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.6.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.6.0
46
+ description: Keep data in sync as you denormalize across any type of relation.
47
+ email: github_public@dz.oib.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - lib/mongoid/alize/macros.rb
53
+ - lib/mongoid/alize/callbacks/to/one_from_many.rb
54
+ - lib/mongoid/alize/callbacks/to/many_from_one.rb
55
+ - lib/mongoid/alize/callbacks/to/many_from_many.rb
56
+ - lib/mongoid/alize/callbacks/to/one_from_one.rb
57
+ - lib/mongoid/alize/callbacks/from/many.rb
58
+ - lib/mongoid/alize/callbacks/from/one.rb
59
+ - lib/mongoid/alize/to_many_callback.rb
60
+ - lib/mongoid/alize/to_one_callback.rb
61
+ - lib/mongoid/alize/to_callback.rb
62
+ - lib/mongoid/alize/callback.rb
63
+ - lib/mongoid/alize/from_callback.rb
64
+ - lib/mongoid_alize.rb
65
+ - spec/app/models/person.rb
66
+ - spec/app/models/head.rb
67
+ - spec/helpers/macros_helper.rb
68
+ - spec/mongoid_alize_spec.rb
69
+ - spec/spec_helper.rb
70
+ - spec/mongoid/alize/callbacks/to/many_from_one_spec.rb
71
+ - spec/mongoid/alize/callbacks/to/one_from_many_spec.rb
72
+ - spec/mongoid/alize/callbacks/to/one_from_one_spec.rb
73
+ - spec/mongoid/alize/callbacks/to/many_from_many_spec.rb
74
+ - spec/mongoid/alize/callbacks/from/one_spec.rb
75
+ - spec/mongoid/alize/callbacks/from/many_spec.rb
76
+ - spec/mongoid/alize/macros_spec.rb
77
+ - spec/mongoid/alize/callback_spec.rb
78
+ homepage: https://github.com/dzello/mongoid_alize
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.23
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Comprehensive field denormalization for Mongoid that stays in sync.
102
+ test_files: []