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,207 @@
1
+ require 'spec_helper'
2
+
3
+ describe "OneEmbeddedPolymorhpicProxy" do
4
+ before do
5
+ @post_class = Doc('Post') do
6
+ key :title, String
7
+ end
8
+ end
9
+
10
+ it "should default to nil" do
11
+ @post_class.one :author, :polymorphic => true, :class => Robot
12
+ @post_class.new.author.should be_nil
13
+ end
14
+
15
+ it "should return nil instead of a proxy" do
16
+ @post_class.one :author, :polymorphic => true, :class => Robot
17
+ nil.should === @post_class.new.author
18
+ end
19
+
20
+ it "should be able to build" do
21
+ @post_class.one :author, :polymorphic => true, :class => Robot
22
+ post = @post_class.create
23
+ author = post.build_author(:serial_number => "1B")
24
+ post.author.should be_instance_of(Robot)
25
+ post.author.should be_new
26
+ post.author.serial_number.should == '1B'
27
+ post.author.should == author
28
+ post.author.post.should == post
29
+ end
30
+
31
+ it "should allow assignment of associated document using a hash" do
32
+ @post_class.one :author, :polymorphic => :true, :class => Robot
33
+
34
+ post = @post_class.new('author' => { 'name' => 'Frank', '_type' => 'Human' })
35
+ post.author.name.should == 'Frank'
36
+ post.author.class.should == Human
37
+
38
+ post.save.should be_truthy
39
+ post.reload
40
+
41
+ post.author.name.should == 'Frank'
42
+ post.author.class.should == Human
43
+ end
44
+
45
+ context "replacing the association" do
46
+ context "with an object" do
47
+ before do
48
+ @post_class.one :author, :polymorphic => true, :class => Robot
49
+ @post = @post_class.create
50
+ @human = Human.new(:name => 'Frank')
51
+ end
52
+
53
+ it "should work" do
54
+ @post.author = @human
55
+ @post.save
56
+ @post.reload
57
+
58
+ @post.author.should == @human
59
+ @post.author.nil?.should be_falsey
60
+ @post.author.class.should == Human
61
+
62
+ new_human = Human.new(:name => 'Emily')
63
+ @post.author = new_human
64
+ @post.author.should == new_human
65
+ end
66
+
67
+ it "should generate a new proxy instead of modifying the existing one" do
68
+ @post.author = @human
69
+ @post.save
70
+ @post.reload
71
+
72
+ @post.author.should == @human
73
+ @post.author.nil?.should be_falsey
74
+
75
+ original_author = @post.author
76
+ original_author.name.should == 'Frank'
77
+ new_human = Human.new(:name => 'Emily')
78
+ @post.author = new_human
79
+ @post.author.should == new_human
80
+
81
+ original_author.name.should == 'Frank'
82
+ end
83
+
84
+ it "should assign _type" do
85
+ @post.author = @human
86
+ @post.author._type.should == "Human"
87
+ end
88
+ end
89
+
90
+ context "with a Hash" do
91
+ before do
92
+ @post_class.one :author, :polymorphic => true, :class => Robot
93
+ @post = @post_class.create
94
+ end
95
+
96
+ it "should convert to an object of the class and work" do
97
+ @post.author = {'serial_number' => '1B'}
98
+ @post.save
99
+ @post.reload
100
+
101
+ @post.author.serial_number.should == '1B'
102
+ @post.author.nil?.should be_falsey
103
+
104
+ @post.author = {'serial_number' => '2C'}
105
+ @post.author.serial_number.should == '2C'
106
+ end
107
+
108
+ it "should convert to an object of _type if given" do
109
+ @post.author = {'name' => 'Frank', '_type' => 'Human'}
110
+ @post.author.name.should == 'Frank'
111
+ @post.author.class.should == Human
112
+ @post.save
113
+ @post.reload
114
+
115
+ @post.author.name.should == 'Frank'
116
+ @post.author.class.should == Human
117
+ end
118
+
119
+ it "should assign _type" do
120
+ @post.author = {'name' => 'Frank', '_type' => 'Human'}
121
+ @post.save
122
+ @post.reload
123
+ @post.author._type.should == "Human"
124
+ end
125
+ end
126
+ end
127
+
128
+ it "should unset the association" do
129
+ @post_class.one :author, :polymorphic => true, :class => Robot
130
+ post = @post_class.create
131
+ human = Human.new
132
+ post.update_attributes!(:author => human)
133
+ post.reload
134
+ post.author = nil
135
+ post.author.should == nil
136
+ end
137
+
138
+ it "should set modularized associated models correctly" do
139
+ @post_class.one :author, :polymorphic => true, :class => Robot
140
+
141
+ post = @post_class.new('author' => {'_type' => 'TrModels::Ambulance', 'license_plate' => 'GGG123', 'icu' => true})
142
+
143
+ post.author.class.should == TrModels::Ambulance
144
+ post.author.license_plate.should == 'GGG123'
145
+ post.author.icu.should be_truthy
146
+ post.save.should be_truthy
147
+
148
+ post = post.reload
149
+ post.author.class.should == TrModels::Ambulance
150
+ post.author.license_plate.should == 'GGG123'
151
+ post.author.icu.should be_truthy
152
+ end
153
+
154
+ it "should not have problem loading root document if embedded one is nil" do
155
+ @post_class.one :author, :polymorphic => true, :class => Robot
156
+ post = @post_class.create
157
+
158
+ lambda {
159
+ @post_class.find(post.id)
160
+ }.should_not raise_error
161
+ end
162
+
163
+ it "should load the parent and root documents for nested embedded documents" do
164
+ @address_class = EDoc('Address') do
165
+ key :city, String
166
+ key :state, String
167
+ end
168
+ @author_class = EDoc('EmbeddedAuthor')
169
+ @author_class.one :address, :polymorphic => true, :class => @address_class
170
+ @post_class.one :author, :polymorphic => true, :class => @author_class
171
+
172
+ post = @post_class.create(:title => 'Post Title', :author => { :name => 'Frank', :address => { :city => 'Boston', :state => 'MA' } })
173
+
174
+ post.author.address._parent_document.should == post.author
175
+ post.author.address._root_document.should == post
176
+ end
177
+
178
+ it "should have boolean method for testing presence" do
179
+ @post_class.one :author, :polymorphic => true, :class => Robot
180
+
181
+ post = @post_class.new
182
+ post.author?.should be_falsey
183
+
184
+ post.author = Human.new(:name => 'Frank')
185
+ post.author?.should be_truthy
186
+ end
187
+
188
+ it "should initialize id for nested embedded document created from hash" do
189
+ @address_class = EDoc('Address') do
190
+ key :city, String
191
+ key :state, String
192
+ end
193
+ @author_class = EDoc('EmbeddedAuthor')
194
+ @author_class.one :address, :polymorphic => true, :class => @address_class
195
+ @post_class.one :author, :polymorphic => true, :class => @author_class
196
+
197
+ post = @post_class.create(:title => 'Post Title', :author => {
198
+ :name => 'Frank',
199
+ :address => {
200
+ :city => 'Boston',
201
+ :state => 'MA'
202
+ }
203
+ })
204
+
205
+ post.author.address.id.should_not be_nil
206
+ end
207
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe "OneEmbeddedProxy" do
4
+ before do
5
+ @post_class = Doc('Post') do
6
+ key :title, String
7
+ end
8
+ @author_class = EDoc('Author') do
9
+ key :name, String
10
+ embedded_in :post
11
+ end
12
+ end
13
+
14
+ it "should default to nil" do
15
+ @post_class.one :author, :class => @author_class
16
+ @post_class.new.author.should be_nil
17
+ end
18
+
19
+ it "should be able to build" do
20
+ @post_class.one :author, :class => @author_class
21
+
22
+ post = @post_class.create
23
+ author = post.build_author(:name => "John")
24
+ post.author.should be_instance_of(@author_class)
25
+ post.author.should be_new
26
+ post.author.name.should == 'John'
27
+ post.author.should == author
28
+ post.author.post.should == post
29
+ end
30
+
31
+ it "should be able to replace the association" do
32
+ @post_class.one :author, :class => @author_class
33
+
34
+ post = @post_class.new
35
+ author = @author_class.new(:name => 'Frank')
36
+ post.author = author
37
+ post.save
38
+ post.reload
39
+
40
+ post.author.should == author
41
+ post.author.nil?.should be_falsey
42
+
43
+ new_author = @author_class.new(:name => 'Emily')
44
+ post.author = new_author
45
+ post.author.should == new_author
46
+ end
47
+
48
+ it "should not have problem loading root document if embedded one is nil" do
49
+ @post_class.one :author, :class => @author_class
50
+ post = @post_class.create
51
+
52
+ lambda {
53
+ @post_class.find(post.id)
54
+ }.should_not raise_error
55
+ end
56
+
57
+ it "should load the parent and root documents for nested embedded documents" do
58
+ @address_class = EDoc('Address') do
59
+ key :city, String
60
+ key :state, String
61
+ end
62
+ @author_class.one :address, :class => @address_class
63
+ @post_class.one :author, :class => @author_class
64
+
65
+ post = @post_class.create(:title => 'Post Title', :author => { :name => 'Frank', :address => { :city => 'Boston', :state => 'MA' } })
66
+
67
+ post.author.address._parent_document.should == post.author
68
+ post.author.address._root_document.should == post
69
+ end
70
+
71
+ it "should have boolean method for testing presence" do
72
+ @post_class.one :author, :class => @author_class
73
+
74
+ post = @post_class.new
75
+ post.author?.should be_falsey
76
+
77
+ post.author = @author_class.new(:name => 'Frank')
78
+ post.author?.should be_truthy
79
+ end
80
+
81
+ it "should initialize id for nested embedded document created from hash" do
82
+ @address_class = EDoc('Address') do
83
+ key :city, String
84
+ key :state, String
85
+ end
86
+ @author_class.one(:address, :class => @address_class)
87
+ @post_class.one(:author, :class => @author_class)
88
+
89
+ post = @post_class.create(:title => 'Post Title', :author => {
90
+ :name => 'Frank',
91
+ :address => {
92
+ :city => 'Boston',
93
+ :state => 'MA'
94
+ }
95
+ })
96
+
97
+ post.author.address.id.should_not be_nil
98
+ end
99
+
100
+ end
@@ -0,0 +1,406 @@
1
+ require 'spec_helper'
2
+
3
+ describe "OneProxy" do
4
+ before do
5
+ @post_class = Doc('Post')
6
+ @author_class = Doc do
7
+ key :name, String
8
+ key :post_id, ObjectId
9
+ end
10
+ end
11
+
12
+ it "should default to nil" do
13
+ @post_class.one :author, :class => @author_class
14
+ @post_class.new.author.nil?.should be_truthy
15
+ end
16
+
17
+ it "should return nil instead of a proxy" do
18
+ @post_class.one :author, :class => @author_class
19
+ nil.should === @post_class.new.author
20
+ end
21
+
22
+ it "should allow assignment of associated document using a hash" do
23
+ @post_class.one :author, :class => @author_class
24
+
25
+ post = @post_class.new('author' => { 'name' => 'Frank' })
26
+ post.author.name.should == 'Frank'
27
+
28
+ post.save.should be_truthy
29
+ post.reload
30
+
31
+ post.author.name.should == 'Frank'
32
+ end
33
+
34
+ context "replacing the association" do
35
+ context "with an object of the class" do
36
+ it "should work" do
37
+ @post_class.one :author, :class => @author_class
38
+
39
+ post = @post_class.new
40
+ author = @author_class.new(:name => 'Frank')
41
+ post.author = author
42
+ post.reload
43
+
44
+ post.author.should == author
45
+ post.author.nil?.should be_falsey
46
+
47
+ new_author = @author_class.new(:name => 'Emily')
48
+ post.author = new_author
49
+ post.author.should == new_author
50
+ end
51
+
52
+ it "should generate a new proxy instead of modifying the existing one" do
53
+ @post_class.one :author, :class => @author_class
54
+
55
+ post = @post_class.new
56
+ author = @author_class.new(:name => 'Frank')
57
+ post.author = author
58
+ post.reload
59
+
60
+ post.author.should == author
61
+ post.author.nil?.should be_falsey
62
+
63
+ original_author = post.author
64
+ original_author.name.should == 'Frank'
65
+ new_author = @author_class.new(:name => 'Emily')
66
+ post.author = new_author
67
+ post.author.should == new_author
68
+
69
+ original_author.name.should == 'Frank'
70
+ end
71
+ end
72
+
73
+ context "with a Hash" do
74
+ it "should convert to an object of the class and work" do
75
+ @post_class.one :author, :class => @author_class
76
+
77
+ post = @post_class.new
78
+ post.author = {'name' => 'Frank'}
79
+ post.reload
80
+
81
+ post.author.name.should == 'Frank'
82
+ post.author.nil?.should be_falsey
83
+
84
+ post.author = {'name' => 'Emily'}
85
+ post.author.name.should == 'Emily'
86
+ end
87
+ end
88
+
89
+ context "with :dependent" do
90
+ context "=> delete" do
91
+ before do
92
+ @post_class.one :author, :class => @author_class, :dependent => :delete
93
+
94
+ @post = @post_class.create
95
+ @author = @author_class.new
96
+ @post.author = @author
97
+ end
98
+
99
+ it "should call delete on the existing document" do
100
+ expect_any_instance_of(@author_class).to receive(:delete).once
101
+ @post.author = @author_class.new
102
+ end
103
+
104
+ it "should remove the existing document from the database" do
105
+ @post.author = @author_class.new
106
+ lambda { @author.reload }.should raise_error(MarkMapper::DocumentNotFound)
107
+ end
108
+
109
+ it "should do nothing if it's the same document" do
110
+ expect_any_instance_of(@author_class).to receive(:delete).never
111
+ @post.author = @author
112
+ end
113
+ end
114
+
115
+ context "=> destory" do
116
+ before do
117
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
118
+
119
+ @post = @post_class.create
120
+ @author = @author_class.new
121
+ @post.author = @author
122
+ end
123
+
124
+ it "should call destroy the existing document" do
125
+ expect_any_instance_of(@author_class).to receive(:destroy).once
126
+ @post.author = @author_class.new
127
+ end
128
+
129
+ it "should remove the existing document from the database" do
130
+ @post.author = @author_class.new
131
+ lambda { @author.reload }.should raise_error(MarkMapper::DocumentNotFound)
132
+ end
133
+
134
+ it "should do nothing if it's the same document" do
135
+ expect_any_instance_of(@author_class).to receive(:destroy).never
136
+ @post.author = @author
137
+ end
138
+ end
139
+
140
+ context "=> nullify" do
141
+ before do
142
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
143
+
144
+ @post = @post_class.create
145
+ @author = @author_class.new
146
+ @post.author = @author
147
+ end
148
+
149
+ it "should nullify the existing document" do
150
+ @author.reload
151
+ @author.post_id.should == @post.id
152
+
153
+ @post.author = @author_class.new
154
+
155
+ @author.reload
156
+ @author.post_id.should be_nil
157
+ end
158
+
159
+ it "should work when it's the same document" do
160
+ old_author = @post.author
161
+ @post.author = @author
162
+ old_author.should == @post.author
163
+ end
164
+ end
165
+
166
+ context "unspecified" do
167
+ it "should nullify the existing document" do
168
+ @post_class.one :author, :class => @author_class
169
+
170
+ post = @post_class.create
171
+ author = @author_class.new
172
+ post.author = author
173
+ author.reload
174
+ author.post_id.should == post.id
175
+
176
+ post.author = @author_class.new
177
+
178
+ author.reload
179
+ author.post_id.should be_nil
180
+ end
181
+ end
182
+ end
183
+
184
+ context "with nil" do
185
+ before do
186
+ @post_class.one :author, :class => @author_class
187
+
188
+ @post = @post_class.new
189
+ @author = @author_class.new(:name => 'Frank')
190
+ @post.author = @author
191
+ end
192
+
193
+ it "should nullify the existing document" do
194
+ @post.author = nil
195
+ @author.reload
196
+ @author.post_id.should be_nil
197
+ end
198
+
199
+ it "should set the target to nil" do
200
+ @post.author = nil
201
+ @post.author.should == nil
202
+ end
203
+ end
204
+ end
205
+
206
+ it "should have boolean method for testing presence" do
207
+ @post_class.one :author, :class => @author_class
208
+
209
+ post = @post_class.new
210
+ post.author?.should be_falsey
211
+
212
+ post.author = @author_class.new(:name => 'Frank')
213
+ post.author?.should be_truthy
214
+ end
215
+
216
+ it "should work with criteria" do
217
+ @post_class.one :primary_author, :class => @author_class, :primary => true
218
+ @post_class.one :author, :class => @author_class, :primary => false
219
+
220
+ post = @post_class.create
221
+ author = @author_class.create(:name => 'Frank', :primary => false, :post_id => post.id)
222
+ primary = @author_class.create(:name => 'Bill', :primary => true, :post_id => post.id)
223
+ post.reload
224
+ post.author.should == author
225
+ post.primary_author.should == primary
226
+ end
227
+
228
+ it "should unset the association" do
229
+ @post_class.one :author, :class => @author_class
230
+ post = @post_class.create
231
+ author = @author_class.create
232
+ post.update_attributes!(:author => author)
233
+ post.reload
234
+ post.author = nil
235
+ post.author.nil?.should be_truthy
236
+ end
237
+
238
+ context "destroying parent with :dependent" do
239
+ context "=> destroy" do
240
+ before do
241
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
242
+
243
+ @post = @post_class.create
244
+ @author = @author_class.new
245
+ @post.author = @author
246
+ end
247
+
248
+ it "should should call destroy on the associated documents" do
249
+ expect_any_instance_of(@author_class).to receive(:destroy).once
250
+ @post.destroy
251
+ end
252
+
253
+ it "should should remove the associated documents" do
254
+ @author_class.count.should == 1
255
+ @post.destroy
256
+ @post.author.should == nil
257
+ @author_class.count.should == 0
258
+ end
259
+ end
260
+
261
+ context "=> delete" do
262
+ before do
263
+ @post_class.one :author, :class => @author_class, :dependent => :delete
264
+
265
+ @post = @post_class.create
266
+ @author = @author_class.new
267
+ @post.author = @author
268
+ end
269
+
270
+ it "should should call delete the associated documents" do
271
+ expect_any_instance_of(@author_class).to receive(:delete).once
272
+ @post.destroy
273
+ end
274
+
275
+ it "should remove the associated documents" do
276
+ @author_class.count.should == 1
277
+ @post.destroy
278
+ @post.author.should == nil
279
+ @author_class.count.should == 0
280
+ end
281
+ end
282
+
283
+ context "=> nullify" do
284
+ it "should should nullify the relationship but not destroy the associated document" do
285
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
286
+
287
+ post = @post_class.create
288
+ author = @author_class.new
289
+ post.author = author
290
+
291
+ @author_class.count.should == 1
292
+ post.destroy
293
+ post.author.should == nil
294
+ @author_class.count.should == 1
295
+
296
+ @author_class.first.should == author
297
+ author.post_id.should == nil
298
+ end
299
+ end
300
+
301
+ context "unspecified" do
302
+ it "should should nullify the relationship but not destroy the associated document" do
303
+ @post_class.one :author, :class => @author_class
304
+
305
+ post = @post_class.create
306
+ author = @author_class.new
307
+ post.author = author
308
+
309
+ @author_class.count.should == 1
310
+ post.destroy
311
+ post.author.should == nil
312
+ @author_class.count.should == 1
313
+
314
+ @author_class.first.should == author
315
+ author.post_id.should == nil
316
+ end
317
+ end
318
+ end
319
+
320
+ context "when building associations" do
321
+ before do
322
+ @post_class.one :author, :class => @author_class
323
+ end
324
+ let(:post) { @post_class.create }
325
+
326
+ context "#build" do
327
+ it "should work" do
328
+ author = post.build_author(:name => 'John')
329
+ post.author.should be_instance_of(@author_class)
330
+ post.author.should be_new
331
+ post.author.name.should == 'John'
332
+ post.author.should == author
333
+ post.author.post_id.should == post.id
334
+ end
335
+
336
+ it "should allow a block" do
337
+ author = post.build_author do |doc|
338
+ doc.name = "John"
339
+ end
340
+ author.name.should == "John"
341
+ end
342
+ end
343
+
344
+ context "#create" do
345
+ it "should work" do
346
+ author = post.create_author(:name => 'John')
347
+ post.author.should be_instance_of(@author_class)
348
+ post.author.should_not be_new
349
+ post.author.name.should == 'John'
350
+ post.author.should == author
351
+ post.author.post_id.should == post.id
352
+ end
353
+
354
+ it "should allow a block" do
355
+ author = post.create_author do |doc|
356
+ doc.name = "John"
357
+ end
358
+ author.name.should == "John"
359
+ end
360
+ end
361
+
362
+
363
+ context "#create!" do
364
+ before do
365
+ @author_class.key :name, String, :required => true
366
+ end
367
+
368
+ it "should raise exception if invalid" do
369
+ expect {
370
+ post.create_author!
371
+ }.to raise_error(MarkMapper::DocumentNotValid)
372
+ end
373
+
374
+ it "should work if valid" do
375
+ author = post.create_author!(:name => 'John')
376
+ post.author.should be_instance_of(@author_class)
377
+ post.author.should_not be_new
378
+ post.author.name.should == 'John'
379
+ post.author.should == author
380
+ post.author.post_id.should == post.id
381
+ end
382
+
383
+ it "should accept a block" do
384
+ author = post.create_author! do |doc|
385
+ doc.name = "John"
386
+ end
387
+ author.name.should == "John"
388
+ end
389
+ end
390
+ end
391
+
392
+ context "namespaced foreign keys" do
393
+ before do
394
+ News::Paper.one :article, :class_name => 'News::Article'
395
+ News::Article.belongs_to :paper, :class_name => 'News::Paper'
396
+
397
+ @paper = News::Paper.create
398
+ end
399
+
400
+ it "should properly infer the foreign key" do
401
+ article = @paper.create_article
402
+ article.should respond_to(:paper_id)
403
+ article.paper_id.should == @paper.id
404
+ end
405
+ end
406
+ end