mark_mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +39 -0
  4. data/examples/attr_accessible.rb +24 -0
  5. data/examples/attr_protected.rb +24 -0
  6. data/examples/cache_key.rb +26 -0
  7. data/examples/custom_types.rb +26 -0
  8. data/examples/identity_map.rb +30 -0
  9. data/examples/identity_map/automatic.rb +2 -0
  10. data/examples/keys.rb +42 -0
  11. data/examples/modifiers/set.rb +27 -0
  12. data/examples/plugins.rb +40 -0
  13. data/examples/querying.rb +39 -0
  14. data/examples/sample_app.rb +43 -0
  15. data/examples/scopes.rb +56 -0
  16. data/examples/validating/embedded_docs.rb +31 -0
  17. data/lib/mark_mapper.rb +125 -0
  18. data/lib/mark_mapper/config.rb +90 -0
  19. data/lib/mark_mapper/connection.rb +60 -0
  20. data/lib/mark_mapper/criteria_hash.rb +194 -0
  21. data/lib/mark_mapper/document.rb +46 -0
  22. data/lib/mark_mapper/embedded_document.rb +32 -0
  23. data/lib/mark_mapper/exceptions.rb +33 -0
  24. data/lib/mark_mapper/extensions/array.rb +27 -0
  25. data/lib/mark_mapper/extensions/boolean.rb +45 -0
  26. data/lib/mark_mapper/extensions/date.rb +29 -0
  27. data/lib/mark_mapper/extensions/duplicable.rb +86 -0
  28. data/lib/mark_mapper/extensions/float.rb +18 -0
  29. data/lib/mark_mapper/extensions/hash.rb +26 -0
  30. data/lib/mark_mapper/extensions/integer.rb +27 -0
  31. data/lib/mark_mapper/extensions/kernel.rb +11 -0
  32. data/lib/mark_mapper/extensions/nil_class.rb +18 -0
  33. data/lib/mark_mapper/extensions/object.rb +30 -0
  34. data/lib/mark_mapper/extensions/object_id.rb +18 -0
  35. data/lib/mark_mapper/extensions/set.rb +20 -0
  36. data/lib/mark_mapper/extensions/string.rb +31 -0
  37. data/lib/mark_mapper/extensions/symbol.rb +87 -0
  38. data/lib/mark_mapper/extensions/time.rb +29 -0
  39. data/lib/mark_mapper/locale/en.yml +5 -0
  40. data/lib/mark_mapper/middleware/identity_map.rb +41 -0
  41. data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
  42. data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
  43. data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
  44. data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
  45. data/lib/mark_mapper/normalizers/integer.rb +19 -0
  46. data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
  47. data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
  48. data/lib/mark_mapper/options_hash.rb +103 -0
  49. data/lib/mark_mapper/pagination.rb +6 -0
  50. data/lib/mark_mapper/pagination/collection.rb +32 -0
  51. data/lib/mark_mapper/pagination/paginator.rb +46 -0
  52. data/lib/mark_mapper/plugins.rb +22 -0
  53. data/lib/mark_mapper/plugins/accessible.rb +61 -0
  54. data/lib/mark_mapper/plugins/active_model.rb +18 -0
  55. data/lib/mark_mapper/plugins/associations.rb +96 -0
  56. data/lib/mark_mapper/plugins/associations/base.rb +98 -0
  57. data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
  58. data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
  59. data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  60. data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
  61. data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
  62. data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
  63. data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
  64. data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  65. data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
  66. data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  67. data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  68. data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  69. data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
  70. data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
  71. data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  72. data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  73. data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
  74. data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
  75. data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
  76. data/lib/mark_mapper/plugins/caching.rb +21 -0
  77. data/lib/mark_mapper/plugins/callbacks.rb +42 -0
  78. data/lib/mark_mapper/plugins/clone.rb +24 -0
  79. data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
  80. data/lib/mark_mapper/plugins/dirty.rb +61 -0
  81. data/lib/mark_mapper/plugins/document.rb +41 -0
  82. data/lib/mark_mapper/plugins/dumpable.rb +22 -0
  83. data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
  84. data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  85. data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
  86. data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
  87. data/lib/mark_mapper/plugins/equality.rb +23 -0
  88. data/lib/mark_mapper/plugins/identity_map.rb +144 -0
  89. data/lib/mark_mapper/plugins/indexable.rb +86 -0
  90. data/lib/mark_mapper/plugins/inspect.rb +16 -0
  91. data/lib/mark_mapper/plugins/keys.rb +470 -0
  92. data/lib/mark_mapper/plugins/keys/key.rb +134 -0
  93. data/lib/mark_mapper/plugins/keys/static.rb +45 -0
  94. data/lib/mark_mapper/plugins/logger.rb +18 -0
  95. data/lib/mark_mapper/plugins/modifiers.rb +140 -0
  96. data/lib/mark_mapper/plugins/pagination.rb +16 -0
  97. data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
  98. data/lib/mark_mapper/plugins/persistence.rb +79 -0
  99. data/lib/mark_mapper/plugins/protected.rb +45 -0
  100. data/lib/mark_mapper/plugins/querying.rb +173 -0
  101. data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
  102. data/lib/mark_mapper/plugins/rails.rb +79 -0
  103. data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  104. data/lib/mark_mapper/plugins/sci.rb +82 -0
  105. data/lib/mark_mapper/plugins/scopes.rb +28 -0
  106. data/lib/mark_mapper/plugins/serialization.rb +109 -0
  107. data/lib/mark_mapper/plugins/timestamps.rb +29 -0
  108. data/lib/mark_mapper/plugins/touch.rb +18 -0
  109. data/lib/mark_mapper/plugins/userstamps.rb +18 -0
  110. data/lib/mark_mapper/plugins/validations.rb +96 -0
  111. data/lib/mark_mapper/query.rb +278 -0
  112. data/lib/mark_mapper/railtie.rb +52 -0
  113. data/lib/mark_mapper/railtie/database.rake +65 -0
  114. data/lib/mark_mapper/translation.rb +10 -0
  115. data/lib/mark_mapper/version.rb +4 -0
  116. data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
  117. data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
  118. data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
  119. data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
  120. data/spec/config/mark_mapper.yml +6 -0
  121. data/spec/examples_spec.rb +25 -0
  122. data/spec/functional/accessible_spec.rb +198 -0
  123. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
  124. data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
  125. data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
  126. data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
  127. data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
  128. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
  129. data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
  130. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
  131. data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
  132. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
  133. data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
  134. data/spec/functional/associations/one_proxy_spec.rb +406 -0
  135. data/spec/functional/associations_spec.rb +48 -0
  136. data/spec/functional/caching_spec.rb +75 -0
  137. data/spec/functional/callbacks_spec.rb +330 -0
  138. data/spec/functional/counter_cache_spec.rb +235 -0
  139. data/spec/functional/dirty_spec.rb +316 -0
  140. data/spec/functional/document_spec.rb +310 -0
  141. data/spec/functional/dumpable_spec.rb +24 -0
  142. data/spec/functional/dynamic_querying_spec.rb +75 -0
  143. data/spec/functional/embedded_document_spec.rb +316 -0
  144. data/spec/functional/equality_spec.rb +20 -0
  145. data/spec/functional/extensions_spec.rb +16 -0
  146. data/spec/functional/identity_map_spec.rb +483 -0
  147. data/spec/functional/keys_spec.rb +339 -0
  148. data/spec/functional/logger_spec.rb +20 -0
  149. data/spec/functional/modifiers_spec.rb +446 -0
  150. data/spec/functional/options_hash_spec.rb +41 -0
  151. data/spec/functional/pagination_spec.rb +89 -0
  152. data/spec/functional/partial_updates_spec.rb +530 -0
  153. data/spec/functional/protected_spec.rb +199 -0
  154. data/spec/functional/querying_spec.rb +984 -0
  155. data/spec/functional/rails_spec.rb +55 -0
  156. data/spec/functional/sci_spec.rb +374 -0
  157. data/spec/functional/scopes_spec.rb +204 -0
  158. data/spec/functional/static_keys_spec.rb +153 -0
  159. data/spec/functional/timestamps_spec.rb +97 -0
  160. data/spec/functional/touch_spec.rb +125 -0
  161. data/spec/functional/userstamps_spec.rb +46 -0
  162. data/spec/functional/validations_spec.rb +416 -0
  163. data/spec/quality_spec.rb +51 -0
  164. data/spec/spec_helper.rb +150 -0
  165. data/spec/support/matchers.rb +15 -0
  166. data/spec/support/models.rb +256 -0
  167. data/spec/symbol_operator_spec.rb +70 -0
  168. data/spec/symbol_spec.rb +9 -0
  169. data/spec/unit/associations/base_spec.rb +146 -0
  170. data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
  171. data/spec/unit/associations/many_association_spec.rb +64 -0
  172. data/spec/unit/associations/one_association_spec.rb +48 -0
  173. data/spec/unit/associations/proxy_spec.rb +103 -0
  174. data/spec/unit/clone_spec.rb +79 -0
  175. data/spec/unit/config_generator_spec.rb +24 -0
  176. data/spec/unit/criteria_hash_spec.rb +218 -0
  177. data/spec/unit/document_spec.rb +251 -0
  178. data/spec/unit/dynamic_finder_spec.rb +125 -0
  179. data/spec/unit/embedded_document_spec.rb +676 -0
  180. data/spec/unit/equality_spec.rb +38 -0
  181. data/spec/unit/exceptions_spec.rb +12 -0
  182. data/spec/unit/extensions_spec.rb +368 -0
  183. data/spec/unit/identity_map_middleware_spec.rb +134 -0
  184. data/spec/unit/inspect_spec.rb +47 -0
  185. data/spec/unit/key_spec.rb +276 -0
  186. data/spec/unit/keys_spec.rb +155 -0
  187. data/spec/unit/mark_mapper_spec.rb +37 -0
  188. data/spec/unit/model_generator_spec.rb +45 -0
  189. data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
  190. data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
  191. data/spec/unit/normalizers/fields_value_spec.rb +45 -0
  192. data/spec/unit/normalizers/hash_key_spec.rb +15 -0
  193. data/spec/unit/normalizers/integer_spec.rb +24 -0
  194. data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
  195. data/spec/unit/normalizers/sort_value_spec.rb +98 -0
  196. data/spec/unit/options_hash_spec.rb +64 -0
  197. data/spec/unit/pagination/collection_spec.rb +30 -0
  198. data/spec/unit/pagination/paginator_spec.rb +118 -0
  199. data/spec/unit/pagination_spec.rb +11 -0
  200. data/spec/unit/plugins_spec.rb +89 -0
  201. data/spec/unit/query_spec.rb +837 -0
  202. data/spec/unit/rails_compatibility_spec.rb +40 -0
  203. data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
  204. data/spec/unit/rails_spec.rb +188 -0
  205. data/spec/unit/serialization_spec.rb +169 -0
  206. data/spec/unit/serializers/json_serializer_spec.rb +218 -0
  207. data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
  208. data/spec/unit/time_zones_spec.rb +44 -0
  209. data/spec/unit/translation_spec.rb +27 -0
  210. data/spec/unit/validations_spec.rb +588 -0
  211. metadata +307 -0
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "BelongsToPolymorphicProxy" do
5
+ before do
6
+ Status.collection.remove
7
+ Project.collection.remove
8
+ end
9
+
10
+ it "should default to nil" do
11
+ status = Status.new
12
+ status.target.nil?.should be_truthy
13
+ status.target.inspect.should == "nil"
14
+ end
15
+
16
+ it "should have boolean presence method" do
17
+ status = Status.new
18
+ status.target?.should be_falsey
19
+
20
+ status.target = Project.new(:name => 'markmapper')
21
+ status.target?.should be_truthy
22
+ end
23
+
24
+ it "should be able to replace the association" do
25
+ status = Status.new(:name => 'Foo!')
26
+ project = Project.new(:name => "markmapper")
27
+ status.target = project
28
+ status.save.should be_truthy
29
+
30
+ status = status.reload
31
+ status.target.nil?.should be_falsey
32
+ status.target_id.should == project._id
33
+ status.target_type.should == "Project"
34
+ status.target.name.should == "markmapper"
35
+ end
36
+
37
+ it "should unset the association" do
38
+ status = Status.new(:name => 'Foo!')
39
+ project = Project.new(:name => "markmapper")
40
+ status.target = project
41
+ status.save.should be_truthy
42
+
43
+ status = status.reload
44
+ status.target = nil
45
+ status.target_type.nil?.should be_truthy
46
+ status.target_id.nil?.should be_truthy
47
+ status.target.nil?.should be_truthy
48
+ end
49
+
50
+ context "association id set but document not found" do
51
+ before do
52
+ @status = Status.new(:name => 'Foo!')
53
+ project = Project.new(:name => "markmapper")
54
+ @status.target = project
55
+ @status.save.should be_truthy
56
+ project.destroy
57
+ @status.reload
58
+ end
59
+
60
+ it "should return nil instead of raising error" do
61
+ @status.target.nil?.should be_truthy
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,255 @@
1
+ require 'spec_helper'
2
+
3
+ describe "BelongsToProxy" do
4
+ before do
5
+ @post_class = Doc()
6
+ @comment_class = Doc do
7
+ key :post_id, ObjectId
8
+ end
9
+ @comment_class.belongs_to :post, :class => @post_class
10
+ end
11
+
12
+ it "should default to nil" do
13
+ @comment_class.new.post.nil?.should be_truthy
14
+ end
15
+
16
+ it "should return nil instead of a proxy" do
17
+ nil.should === @comment_class.new.post
18
+ end
19
+
20
+ it "should have boolean presence method" do
21
+ comment = @comment_class.new(:name => 'Foo!')
22
+ comment.post?.should be_falsey
23
+
24
+ comment.post = @post_class.new(:name => 'markmapper')
25
+ comment.post?.should be_truthy
26
+ end
27
+
28
+ it "should allow overriding association methods" do
29
+ @comment_class.class_eval do
30
+ def post?
31
+ super
32
+ end
33
+ end
34
+
35
+ instance = @comment_class.new
36
+ instance.post?.should be_falsey
37
+ instance.post = @post_class.new
38
+ instance.post?.should be_truthy
39
+ end
40
+
41
+ it "should be able to replace the association" do
42
+ post = @post_class.new(:name => 'markmapper')
43
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
44
+ comment.save.should be_truthy
45
+
46
+ comment = comment.reload
47
+ comment.post.should == post
48
+ comment.post.nil?.should be_falsey
49
+ end
50
+
51
+ it "should not reload the association when replacing" do
52
+ post = @post_class.new(:name => 'markmapper')
53
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
54
+ comment.post.proxy_target.object_id.should == post.object_id
55
+ end
56
+
57
+ it "should properly assign the associated object when assigning the association with create" do
58
+ child_class = Doc('Child')
59
+ parent_class = Doc('Parent')
60
+
61
+ parent_class.one :child, :class => child_class
62
+ child_class.belongs_to :parent, :class => parent_class
63
+
64
+ child = child_class.create(:parent => parent_class.create)
65
+ child.parent.child.should == child
66
+ end
67
+
68
+ it "should generate a new proxy when replacing the association" do
69
+ post1 = @post_class.create(:name => 'post1')
70
+ post2 = @post_class.create(:name => 'post2')
71
+
72
+ comment = @comment_class.new(:name => 'Foo!', :post => post1)
73
+ comment.save.should be_truthy
74
+
75
+
76
+ comment = comment.reload
77
+ comment.post.should == post1
78
+ comment.post.nil?.should be_falsey
79
+
80
+ original_post = comment.post
81
+ original_post.name.should == 'post1'
82
+
83
+ comment.post = post2
84
+ comment.post.name.should == 'post2'
85
+ original_post.name.should == 'post1'
86
+ end
87
+
88
+ it "should unset the association" do
89
+ post = @post_class.new(:name => 'markmapper')
90
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
91
+ comment.save.should be_truthy
92
+
93
+ comment = comment.reload
94
+ comment.post = nil
95
+ comment.post.nil?.should be_truthy
96
+ end
97
+
98
+ it "should return nil if id set but document not found" do
99
+ id = MarkLogic::ObjectId.new
100
+ @comment_class.new(:name => 'Foo', :post_id => id).post.nil?.should be_truthy
101
+ end
102
+
103
+ it "should define foreign key if it doesn't exist" do
104
+ @category_class = Doc()
105
+ @post_class.belongs_to :category, :class => @category_class
106
+
107
+ @post_class.key?(:category_id).should be_truthy
108
+ end
109
+
110
+ it "should not define foreign key if it already exists" do
111
+ @category_class = Doc()
112
+ @post_class.key :category_id, String
113
+ @post_class.belongs_to :category, :class => @category_class
114
+
115
+ @post_class.keys['category_id'].type.should == String
116
+ end
117
+
118
+ context ":dependent" do
119
+ before do
120
+ # FIXME: make use of already defined models
121
+ class ::Property
122
+ include MarkMapper::Document
123
+ end
124
+ Property.collection.remove
125
+
126
+ class ::Thing
127
+ include MarkMapper::Document
128
+ key :name, String
129
+ end
130
+ Thing.collection.remove
131
+ end
132
+
133
+ after do
134
+ Object.send :remove_const, 'Property' if defined?(::Property)
135
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
136
+ end
137
+
138
+ context "=> destroy" do
139
+ before do
140
+ Property.key :thing_id, ObjectId
141
+ Property.belongs_to :thing, :dependent => :destroy
142
+ Thing.many :properties
143
+
144
+ @thing = Thing.create(:name => "Tree")
145
+ @property1 = Property.create
146
+ @property2 = Property.create
147
+ @property3 = Property.create
148
+ @thing.properties << @property1
149
+ @thing.properties << @property2
150
+ @thing.properties << @property3
151
+ end
152
+
153
+ it "should not execute on a belongs_to association" do
154
+ Thing.count.should == 1
155
+ @property1.destroy
156
+ Thing.count.should == 1
157
+ end
158
+ end
159
+ end
160
+
161
+ context "when creating documents" do
162
+ let(:comment) { @comment_class.create }
163
+
164
+ before do
165
+ @post_class.key :title, String, :required => true
166
+ @comment_class.belongs_to :post, :class => @post_class
167
+ end
168
+
169
+ context "#build" do
170
+ it "should work" do
171
+ post = comment.build_post(:title => 'Hello, world!')
172
+ comment.post.should be_instance_of(@post_class)
173
+ comment.post.should be_new
174
+ comment.post.title.should == 'Hello, world!'
175
+ comment.post.should == post
176
+ comment.post_id.should == post.id
177
+ end
178
+
179
+ it "should accept a block" do
180
+ comment.build_post(:title => 'Hello, world!') do |post|
181
+ post.title = "Hello world!"
182
+ end
183
+ comment.post.title.should == "Hello world!"
184
+ end
185
+ end
186
+
187
+ context "#create" do
188
+ it "should work" do
189
+ post = comment.create_post(:title => 'Hello, world!')
190
+ comment.post.should be_instance_of(@post_class)
191
+ comment.post.should_not be_new
192
+ comment.post.title.should == 'Hello, world!'
193
+ comment.post.should == post
194
+ comment.post_id.should == post.id
195
+ end
196
+
197
+ it "should accept a block" do
198
+ comment.create_post(:title => 'Hello, world!') do |post|
199
+ post.title = "Hello world!"
200
+ end
201
+ comment.post.title.should == "Hello world!"
202
+ end
203
+ end
204
+
205
+ context "#create!" do
206
+ it "should accept a block" do
207
+ comment.create_post! do |post|
208
+ post.title = "Hello world!"
209
+ end
210
+ comment.post.title.should == "Hello world!"
211
+ end
212
+
213
+ it "should raise exception if invalid" do
214
+ expect { comment.create_post! }.to raise_error(MarkMapper::DocumentNotValid)
215
+ end
216
+
217
+ it "should work if valid" do
218
+ post = comment.create_post!(:title => 'Hello, world!')
219
+ comment.post.should be_instance_of(@post_class)
220
+ comment.post.should_not be_new
221
+ comment.post.title.should == 'Hello, world!'
222
+ comment.post.should == post
223
+ comment.post_id.should == post.id
224
+ end
225
+ end
226
+ end
227
+
228
+ context 'autosave' do
229
+ it 'should not be true by default' do
230
+ @comment_class.associations[:post].options[:autosave].should_not be_truthy
231
+ end
232
+
233
+ it 'should save parent changes when true' do
234
+ @comment_class.associations[:post].options[:autosave] = true
235
+
236
+ comment = @comment_class.create
237
+ post = comment.create_post(:title => 'Hello, world!')
238
+
239
+ comment.post.attributes = {:title => 'Hi, world.'}
240
+ comment.save
241
+
242
+ post.reload.title.should == 'Hi, world.'
243
+ end
244
+
245
+ it 'should not save parent changes when false' do
246
+ comment = @comment_class.create
247
+ post = comment.create_post(:title => 'Hello, world!')
248
+
249
+ comment.post.attributes = {:title => 'Hi, world.'}
250
+ comment.save
251
+
252
+ post.reload.title.should == 'Hello, world!'
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,349 @@
1
+ require 'spec_helper'
2
+
3
+ describe "InArrayProxy" do
4
+ context "description" do
5
+ before do
6
+ class ::List
7
+ include MarkMapper::Document
8
+ key :name, String, :required => true
9
+ end
10
+
11
+ class ::User
12
+ include MarkMapper::Document
13
+ key :name, String, :required => true
14
+ key :list_ids, Array
15
+ many :lists, :in => :list_ids
16
+ end
17
+ User.collection.remove
18
+ List.collection.remove
19
+ end
20
+
21
+ after do
22
+ Object.send :remove_const, 'List' if defined?(::List)
23
+ Object.send :remove_const, 'User' if defined?(::User)
24
+ end
25
+
26
+ it "should default reader to empty array" do
27
+ User.new.lists.should == []
28
+ end
29
+
30
+ it "should allow adding to association like it was an array" do
31
+ user = User.new(:name => 'John')
32
+ user.lists << List.new(:name => 'Foo1!')
33
+ user.lists.push List.new(:name => 'Foo2!')
34
+ user.lists.concat List.new(:name => 'Foo3!')
35
+ user.lists.size.should == 3
36
+ end
37
+
38
+ it "should ignore adding duplicate ids" do
39
+ user = User.create(:name => 'John')
40
+ list = List.create(:name => 'Foo')
41
+ user.lists << list
42
+ user.lists << list
43
+ user.lists << list
44
+
45
+ user.list_ids.should == [list.id]
46
+ user.lists.count.should == 1
47
+ end
48
+
49
+ it "should be able to replace the association" do
50
+ user = User.new(:name => 'John')
51
+ list = List.new(:name => 'Foo')
52
+ user.lists = [list]
53
+ user.save.should be_truthy
54
+
55
+ user.reload
56
+ user.list_ids.should == [list.id]
57
+ user.lists.size.should == 1
58
+ user.lists[0].name.should == 'Foo'
59
+ end
60
+
61
+ context "create" do
62
+ before do
63
+ @user = User.create(:name => 'John')
64
+ @list = @user.lists.create(:name => 'Foo!')
65
+ end
66
+
67
+ it "should add id to key" do
68
+ @user.list_ids.should include(@list.id)
69
+ end
70
+
71
+ it "should persist id addition to key in database" do
72
+ @user.reload
73
+ @user.list_ids.should include(@list.id)
74
+ end
75
+
76
+ it "should add doc to association" do
77
+ @user.lists.should include(@list)
78
+ end
79
+
80
+ it "should save doc" do
81
+ @list.should_not be_new
82
+ end
83
+
84
+ it "should reset cache" do
85
+ @user.lists.size.should == 1
86
+ @user.lists.create(:name => 'Moo!')
87
+ @user.lists.size.should == 2
88
+ end
89
+ end
90
+
91
+ context "create!" do
92
+ before do
93
+ @user = User.create(:name => 'John')
94
+ @list = @user.lists.create!(:name => 'Foo!')
95
+ end
96
+
97
+ it "should add id to key" do
98
+ @user.list_ids.should include(@list.id)
99
+ end
100
+
101
+ it "should persist id addition to key in database" do
102
+ @user.reload
103
+ @user.list_ids.should include(@list.id)
104
+ end
105
+
106
+ it "should add doc to association" do
107
+ @user.lists.should include(@list)
108
+ end
109
+
110
+ it "should save doc" do
111
+ @list.should_not be_new
112
+ end
113
+
114
+ it "should raise exception if invalid" do
115
+ expect {
116
+ @user.lists.create!
117
+ }.to raise_error(MarkMapper::DocumentNotValid)
118
+ end
119
+
120
+ it "should reset cache" do
121
+ @user.lists.size.should == 1
122
+ @user.lists.create!(:name => 'Moo!')
123
+ @user.lists.size.should == 2
124
+ end
125
+ end
126
+
127
+ context "Finding scoped to association" do
128
+ before do
129
+ @user = User.create(:name => 'John')
130
+ @user2 = User.create(:name => 'Brandon')
131
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
132
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
133
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
134
+ end
135
+
136
+ context "all" do
137
+ it "should work" do
138
+ @user.lists.all(:order => :position.asc).should == [@list1, @list2]
139
+ end
140
+
141
+ it "should work with conditions" do
142
+ @user.lists.all(:name => 'Foo 1').should == [@list1]
143
+ end
144
+
145
+ it "should not hit the database if ids key is empty" do
146
+ @user.list_ids = []
147
+ expect(@user.lists).to receive(:query).never
148
+ @user.lists.all.should == []
149
+ end
150
+ end
151
+
152
+ context "first" do
153
+ it "should work" do
154
+ @user.lists.first(:order => 'position').should == @list1
155
+ end
156
+
157
+ it "should work with conditions" do
158
+ @user.lists.first(:position => 2).should == @list2
159
+ end
160
+
161
+ it "should not hit the database if ids key is empty" do
162
+ @user.list_ids = []
163
+ expect(@user.lists).to receive(:query).never
164
+ @user.lists.first.should be_nil
165
+ end
166
+ end
167
+
168
+ context "last" do
169
+ it "should work" do
170
+ @user.lists.last(:order => 'position').should == @list2
171
+ end
172
+
173
+ it "should work with conditions" do
174
+ @user.lists.last(:position => 2, :order => 'position').should == @list2
175
+ end
176
+
177
+ it "should not hit the database if ids key is empty" do
178
+ @user.list_ids = []
179
+ expect(@user.lists).to receive(:query).never
180
+ @user.lists.last.should be_nil
181
+ end
182
+ end
183
+
184
+ context "with one id" do
185
+ it "should work for id in association" do
186
+ @user.lists.find(@list1.id).should == @list1
187
+ end
188
+
189
+ it "should work with string ids" do
190
+ @user.lists.find(@list1.id.to_s).should == @list1
191
+ end
192
+
193
+ it "should not work for id not in association" do
194
+ @user.lists.find(@list3.id).should be_nil
195
+ end
196
+
197
+ it "should raise error when using ! and not found" do
198
+ expect {
199
+ @user.lists.find!(@list3.id)
200
+ }.to raise_error(MarkMapper::DocumentNotFound)
201
+ end
202
+ end
203
+
204
+ context "with multiple ids" do
205
+ it "should work for ids in association" do
206
+ @user.lists.find(@list1.id, @list2.id).should =~ [@list1, @list2]
207
+ end
208
+
209
+ it "should not work for ids not in association" do
210
+ @user.lists.find(@list1.id, @list2.id, @list3.id).should =~ [@list1, @list2]
211
+ end
212
+ end
213
+
214
+ context "with #paginate" do
215
+ before do
216
+ @lists = @user.lists.paginate(:per_page => 1, :page => 1, :order => 'position')
217
+ end
218
+
219
+ it "should return total pages" do
220
+ @lists.total_pages.should == 2
221
+ end
222
+
223
+ it "should return total entries" do
224
+ @lists.total_entries.should == 2
225
+ end
226
+
227
+ it "should return the subject" do
228
+ @lists.collect(&:name).should == ['Foo 1']
229
+ end
230
+
231
+ it "should not hit the database if ids key is empty" do
232
+ @user.list_ids = []
233
+ expect(@user.lists).to receive(:query).never
234
+ @user.lists.paginate(:page => 1).should == []
235
+ end
236
+ end
237
+
238
+ context "dynamic finders" do
239
+ it "should work with single key" do
240
+ @user.lists.find_by_name('Foo 1').should == @list1
241
+ @user.lists.find_by_name!('Foo 1').should == @list1
242
+ @user.lists.find_by_name('Foo 3').should be_nil
243
+ end
244
+
245
+ it "should work with multiple keys" do
246
+ @user.lists.find_by_name_and_position('Foo 1', 1).should == @list1
247
+ @user.lists.find_by_name_and_position!('Foo 1', 1).should == @list1
248
+ @user.lists.find_by_name_and_position('Foo 3', 1).should be_nil
249
+ end
250
+
251
+ it "should raise error when using ! and not found" do
252
+ expect {
253
+ @user.lists.find_by_name!('Foo 3')
254
+ }.to raise_error(MarkMapper::DocumentNotFound)
255
+ end
256
+
257
+ context "find_or_create_by" do
258
+ it "should not create document if found" do
259
+ lambda {
260
+ list = @user.lists.find_or_create_by_name('Foo 1')
261
+ list.should == @list1
262
+ }.should_not change { List.count }
263
+ end
264
+
265
+ it "should create document if not found" do
266
+ lambda {
267
+ list = @user.lists.find_or_create_by_name('Home')
268
+ @user.lists.should include(list)
269
+ }.should change { List.count }
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ context "count" do
276
+ before do
277
+ @user = User.create(:name => 'John')
278
+ @user2 = User.create(:name => 'Brandon')
279
+ @list1 = @user.lists.create!(:name => 'Foo 1')
280
+ @list2 = @user.lists.create!(:name => 'Foo 2')
281
+ @list3 = @user2.lists.create!(:name => 'Foo 3')
282
+ end
283
+
284
+ it "should return number of ids" do
285
+ @user.lists.count.should == 2
286
+ @user2.lists.count.should == 1
287
+ end
288
+
289
+ it "should return correct count when given criteria" do
290
+ @user.lists.count(:name => 'Foo 1').should == 1
291
+ @user2.lists.count(:name => 'Foo 1').should == 0
292
+ end
293
+
294
+ it "should not hit the database if ids key is empty" do
295
+ @user.list_ids = []
296
+ expect(@user.lists).to receive(:query).never
297
+ @user.lists.count(:name => 'Foo 1').should == 0
298
+ end
299
+ end
300
+
301
+ context "Removing documents" do
302
+ before do
303
+ @user = User.create(:name => 'John')
304
+ @user2 = User.create(:name => 'Brandon')
305
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
306
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
307
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
308
+ end
309
+
310
+ context "destroy_all" do
311
+ it "should work" do
312
+ @user.lists.count.should == 2
313
+ @user.lists.destroy_all
314
+ @user.lists.count.should == 0
315
+ end
316
+
317
+ it "should work with conditions" do
318
+ @user.lists.count.should == 2
319
+ @user.lists.destroy_all(:name => 'Foo 1')
320
+ @user.lists.count.should == 1
321
+ end
322
+ end
323
+
324
+ context "delete_all" do
325
+ it "should work" do
326
+ @user.lists.count.should == 2
327
+ @user.lists.delete_all
328
+ @user.lists.count.should == 0
329
+ end
330
+
331
+ it "should work with conditions" do
332
+ @user.lists.count.should == 2
333
+ @user.lists.delete_all(:name => 'Foo 1')
334
+ @user.lists.count.should == 1
335
+ end
336
+ end
337
+
338
+ it "should work with nullify" do
339
+ @user.lists.count.should == 2
340
+
341
+ lambda {
342
+ @user.lists.nullify
343
+ }.should_not change { List.count }
344
+
345
+ @user.lists.count.should == 0
346
+ end
347
+ end
348
+ end
349
+ end