mark_mapper 0.0.1

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.
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