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,48 @@
1
+ require 'spec_helper'
2
+ require 'support/models'
3
+
4
+ module AssociationsSpec
5
+ describe "Associations" do
6
+ it "should allow changing class names" do
7
+ class AwesomeUser
8
+ include MarkMapper::Document
9
+
10
+ many :posts, :class_name => 'AssociationsSpec::AwesomePost', :foreign_key => :creator_id
11
+ end
12
+ AwesomeUser.collection.remove
13
+
14
+ class AwesomeTag
15
+ include MarkMapper::EmbeddedDocument
16
+
17
+ key :name, String
18
+ key :post_id, ObjectId
19
+
20
+ belongs_to :post, :class_name => 'AssociationsSpec::AwesomeUser'
21
+ end
22
+
23
+ class AwesomePost
24
+ include MarkMapper::Document
25
+
26
+ key :creator_id, ObjectId
27
+
28
+ belongs_to :creator, :class_name => 'AssociationsSpec::AwesomeUser'
29
+ many :tags, :class_name => 'AssociationsSpec::AwesomeTag', :foreign_key => :post_id
30
+ end
31
+
32
+ AwesomeUser.collection.remove
33
+ AwesomePost.collection.remove
34
+
35
+ user = AwesomeUser.create
36
+ tag1 = AwesomeTag.new(:name => 'awesome')
37
+ tag2 = AwesomeTag.new(:name => 'grand')
38
+ post1 = AwesomePost.create(:creator => user, :tags => [tag1])
39
+ post2 = AwesomePost.create(:creator => user, :tags => [tag2])
40
+
41
+ user.reload
42
+ user.posts.should =~ [post1, post2]
43
+
44
+ post1 = post1.reload
45
+ post1.tags.should == [tag1]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Caching" do
4
+ before do
5
+ @klass = Class.new do
6
+ extend MarkMapper::Plugins
7
+ plugin MarkMapper::Plugins::Caching
8
+ end
9
+ allow(@klass).to receive(:name).and_return('Post')
10
+ allow_any_instance_of(@klass).to receive(:persisted?).and_return(true)
11
+ allow_any_instance_of(@klass).to receive(:[]).and_return(nil)
12
+ allow_any_instance_of(@klass).to receive(:[]=).and_return(nil)
13
+ end
14
+
15
+ context "new" do
16
+ before do
17
+ @doc = @klass.new
18
+ allow(@doc).to receive(:persisted?).and_return(false)
19
+ end
20
+
21
+ it "should be class/new" do
22
+ @doc.cache_key.should == 'Post/new'
23
+ end
24
+
25
+ it "should work with suffix" do
26
+ @doc.cache_key(:foo).
27
+ should == 'Post/new/foo'
28
+
29
+ @doc.cache_key(:foo, :bar).
30
+ should == 'Post/new/foo/bar'
31
+ end
32
+ end
33
+
34
+ context "not new" do
35
+ before do
36
+ @object_id = MarkLogic::ObjectId.new
37
+ @doc = @klass.new
38
+ allow(@doc).to receive(:persisted).and_return(true)
39
+ allow(@doc).to receive(:id).and_return(@object_id)
40
+ end
41
+
42
+ context "with updated_at" do
43
+ before do
44
+ time = Time.utc(2010, 6, 20, 8, 10, 7)
45
+ allow(@doc).to receive(:[]).with(:updated_at).and_return(time)
46
+ end
47
+
48
+ it "should be class/id-timestamp" do
49
+ @doc.cache_key.should == "Post/#{@object_id}-20100620081007"
50
+ end
51
+
52
+ it "should work with suffix" do
53
+ @doc.cache_key(:foo).
54
+ should == "Post/#{@object_id}-20100620081007/foo"
55
+
56
+ @doc.cache_key(:foo, :bar).
57
+ should == "Post/#{@object_id}-20100620081007/foo/bar"
58
+ end
59
+ end
60
+
61
+ context "without updated_at" do
62
+ it "should be class/id" do
63
+ @doc.cache_key.should == "Post/#{@object_id}"
64
+ end
65
+
66
+ it "should work with suffix" do
67
+ @doc.cache_key(:foo).
68
+ should == "Post/#{@object_id}/foo"
69
+
70
+ @doc.cache_key(:foo, :bar, :baz).
71
+ should == "Post/#{@object_id}/foo/bar/baz"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,330 @@
1
+ require 'spec_helper'
2
+
3
+ module CallbacksSupport
4
+ def self.included base
5
+ base.key :name, String
6
+
7
+ [ :before_validation, :after_validation,
8
+ :before_create, :after_create,
9
+ :before_update, :after_update,
10
+ :before_save, :after_save,
11
+ :before_destroy, :after_destroy
12
+ ].each do |callback|
13
+ base.send(callback) do
14
+ history << callback.to_sym
15
+ end
16
+ end
17
+ end
18
+
19
+ def history
20
+ @history ||= []
21
+ end
22
+
23
+ def clear_history
24
+ embedded_associations.each { |a| self.send(a.name).each(&:clear_history) }
25
+ @history = nil
26
+ end
27
+ end
28
+
29
+ describe "Callbacks" do
30
+ CreateCallbackOrder = [
31
+ :before_validation,
32
+ :after_validation,
33
+ :before_save,
34
+ :before_create,
35
+ :after_create,
36
+ :after_save
37
+ ]
38
+
39
+ UpdateCallbackOrder = [
40
+ :before_validation,
41
+ :after_validation,
42
+ :before_save,
43
+ :before_update,
44
+ :after_update,
45
+ :after_save
46
+ ]
47
+
48
+ context "Defining and running callbacks on documents" do
49
+ before do
50
+ @document = Doc { include CallbacksSupport }
51
+ end
52
+
53
+ it "should get the order right for creating documents" do
54
+ doc = @document.create(:name => 'John Nunemaker')
55
+ doc.history.should == CreateCallbackOrder
56
+ end
57
+
58
+ it "should get the order right for updating documents" do
59
+ doc = @document.create(:name => 'John Nunemaker')
60
+ doc.clear_history
61
+ doc.name = 'John'
62
+ doc.save
63
+ doc.history.should == UpdateCallbackOrder
64
+ end
65
+
66
+ it "should work for before and after validation" do
67
+ doc = @document.new(:name => 'John Nunemaker')
68
+ doc.valid?
69
+ doc.history.should include(:before_validation)
70
+ doc.history.should include(:after_validation)
71
+ end
72
+
73
+ it "should work for before and after create" do
74
+ doc = @document.create(:name => 'John Nunemaker')
75
+ doc.history.should include(:before_create)
76
+ doc.history.should include(:after_create)
77
+ end
78
+
79
+ it "should work for before and after update" do
80
+ doc = @document.create(:name => 'John Nunemaker')
81
+ doc.name = 'John Doe'
82
+ doc.save
83
+ doc.history.should include(:before_update)
84
+ doc.history.should include(:after_update)
85
+ end
86
+
87
+ it "should work for before and after save" do
88
+ doc = @document.new
89
+ doc.name = 'John Doe'
90
+ doc.save
91
+ doc.history.should include(:before_save)
92
+ doc.history.should include(:after_save)
93
+ end
94
+
95
+ it "should work for before and after destroy" do
96
+ doc = @document.create(:name => 'John Nunemaker')
97
+ doc.destroy
98
+ doc.history.should include(:before_destroy)
99
+ doc.history.should include(:after_destroy)
100
+ end
101
+ end
102
+
103
+ context "Defining and running callbacks on many embedded documents" do
104
+ before do
105
+ @root_class = Doc { include CallbacksSupport }
106
+ @child_class = EDoc { include CallbacksSupport }
107
+ @grand_child_class = EDoc { include CallbacksSupport }
108
+
109
+ @root_class.many :children, :class => @child_class
110
+ @child_class.many :children, :class => @grand_child_class
111
+ end
112
+
113
+ it "should get the order right based on root document creation" do
114
+ grand = @grand_child_class.new(:name => 'Grand Child')
115
+ child = @child_class.new(:name => 'Child', :children => [grand])
116
+ root = @root_class.create(:name => 'Parent', :children => [child])
117
+
118
+ root.children.first.history.should == CreateCallbackOrder
119
+ root.children.first.children.first.history.should == CreateCallbackOrder
120
+ end
121
+
122
+ it "should get the order right based on root document updating" do
123
+ grand = @grand_child_class.new(:name => 'Grand Child')
124
+ child = @child_class.new(:name => 'Child', :children => [grand])
125
+ root = @root_class.create(:name => 'Parent', :children => [child])
126
+ root.clear_history
127
+ root.update_attributes(:name => 'Updated Parent')
128
+
129
+ root.children.first.history.should == UpdateCallbackOrder
130
+ root.children.first.children.first.history.should == UpdateCallbackOrder
131
+ end
132
+
133
+ it "should work for before and after destroy" do
134
+ grand = @grand_child_class.new(:name => 'Grand Child')
135
+ child = @child_class.new(:name => 'Child', :children => [grand])
136
+ root = @root_class.create(:name => 'Parent', :children => [child])
137
+ root.destroy
138
+ child = root.children.first
139
+ child.history.should include(:before_destroy)
140
+ child.history.should include(:after_destroy)
141
+
142
+ grand = root.children.first.children.first
143
+ grand.history.should include(:before_destroy)
144
+ grand.history.should include(:after_destroy)
145
+ end
146
+
147
+ it "should not attempt to run callback defined on root that is not defined on embedded association" do
148
+ @root_class.define_callbacks :after_publish
149
+ @root_class.after_save { |d| d.run_callbacks(:after_publish) }
150
+
151
+ expect {
152
+ child = @child_class.new(:name => 'Child')
153
+ root = @root_class.create(:name => 'Parent', :children => [child])
154
+ child.history.should_not include(:after_publish)
155
+ }.to_not raise_error
156
+ end
157
+ end
158
+
159
+ context "By default" do
160
+ it "should not run callbacks when no callbacks were explicitly defined" do
161
+ EDoc { key :name, String }.embedded_callbacks_off?.should == true
162
+ end
163
+
164
+ it "should run callbacks when a callback was explicitly defined" do
165
+ EDoc {
166
+ key :name, String
167
+ before_save :no_op
168
+ def noop; end
169
+ }.embedded_callbacks_on?.should == true
170
+ end
171
+ end
172
+
173
+ context "Turning embedded callbacks off" do
174
+ before do
175
+ @root_class = Doc { include CallbacksSupport; embedded_callbacks_off }
176
+ @child_class = EDoc { include CallbacksSupport; embedded_callbacks_off }
177
+ @grand_child_class = EDoc { include CallbacksSupport; embedded_callbacks_off }
178
+
179
+ @root_class.many :children, :class => @child_class
180
+ @child_class.many :children, :class => @grand_child_class
181
+ end
182
+
183
+ it "should not run create callbacks" do
184
+ grand = @grand_child_class.new(:name => 'Grand Child')
185
+ child = @child_class.new(:name => 'Child', :children => [grand])
186
+ root = @root_class.create(:name => 'Parent', :children => [child])
187
+
188
+ root.children.first.history.should == []
189
+ root.children.first.children.first.history.should == []
190
+ end
191
+
192
+ it "should not run update callbacks" do
193
+ grand = @grand_child_class.new(:name => 'Grand Child')
194
+ child = @child_class.new(:name => 'Child', :children => [grand])
195
+ root = @root_class.create(:name => 'Parent', :children => [child])
196
+ root.clear_history
197
+ root.update_attributes(:name => 'Updated Parent')
198
+
199
+ root.children.first.history.should == []
200
+ root.children.first.children.first.history.should == []
201
+ end
202
+
203
+ it "should not run destroy callbacks" do
204
+ grand = @grand_child_class.new(:name => 'Grand Child')
205
+ child = @child_class.new(:name => 'Child', :children => [grand])
206
+ root = @root_class.create(:name => 'Parent', :children => [child])
207
+ root.destroy
208
+ child = root.children.first
209
+ child.history.should == []
210
+
211
+ grand = root.children.first.children.first
212
+ grand.history.should == []
213
+ end
214
+ end
215
+
216
+ context "Running validation callbacks with conditional execution" do
217
+ let(:document) do
218
+ Doc do
219
+ include CallbacksSupport
220
+ key :message, String
221
+
222
+ before_validation :set_message, :on => :create
223
+
224
+ def set_message
225
+ self['message'] = 'Hi!'
226
+ end
227
+ end
228
+ end
229
+
230
+ it 'should run callback on create' do
231
+ doc = document.create
232
+ doc.history.should include(:before_validation)
233
+ doc.message.should == 'Hi!'
234
+ end
235
+
236
+ it 'should skip callback on update' do
237
+ doc = document.create
238
+ doc.message = 'Ho!'
239
+ doc.save
240
+ doc.message.should == 'Ho!'
241
+ end
242
+ end
243
+
244
+ describe "after_find" do
245
+ before do
246
+ @found_objects = []
247
+ found_objects = @found_objects # use a local for closure
248
+
249
+ @doc_class = Doc("User") do
250
+ after_find :set_found_object
251
+
252
+ define_method :set_found_object do
253
+ found_objects << self
254
+ end
255
+ end
256
+ end
257
+
258
+ it "should run after finding an object with find!" do
259
+ @doc = @doc_class.create!
260
+
261
+ @doc_class.find!(@doc.id)
262
+ @found_objects.should == [@doc]
263
+ end
264
+
265
+ it "should not have run if nothing was queried" do
266
+ @found_objects.should == []
267
+ end
268
+
269
+ it "should run for multiple objects" do
270
+ @doc1 = @doc_class.create!
271
+ @doc2 = @doc_class.create!
272
+
273
+ @doc_class.all
274
+ @found_objects.should =~ [@doc1, @doc2]
275
+ end
276
+
277
+ it "should run after finding an object through the query proxy" do
278
+ @doc = @doc_class.create!
279
+ @doc_class.where(:_id => @doc.id).first
280
+ @found_objects.should == [@doc]
281
+ end
282
+
283
+ it "should still return the object" do
284
+ @doc = @doc_class.create!
285
+ @doc_class.where(:_id => @doc.id).first.should == @doc
286
+ end
287
+
288
+ it "should not bail if the method return false" do
289
+ @doc_class = Doc("User") do
290
+ after_find :set_found_object
291
+
292
+ define_method :set_found_object do
293
+ false
294
+ end
295
+ end
296
+
297
+ @doc = @doc_class.create!
298
+ @doc_class.where(:_id => @doc.id).first.should == @doc
299
+ end
300
+ end
301
+
302
+ describe "after_initialize" do
303
+ before do
304
+ @objects = []
305
+ objects = @objects
306
+
307
+ @doc_class = Doc("User") do
308
+ after_initialize :set_initialized_object
309
+
310
+ define_method :set_initialized_object do
311
+ objects << self
312
+ end
313
+ end
314
+ end
315
+
316
+ it "should be triggered for objects created with new" do
317
+ @objects.should == []
318
+ obj = @doc_class.new
319
+ @objects.should == [obj]
320
+ end
321
+
322
+ it "should be triggered for objects found in the db" do
323
+ @doc = @doc_class.create!
324
+ @objects.clear # don't re-assign as we want the operation to be in place
325
+
326
+ @doc_class.all
327
+ @objects.should == [@doc]
328
+ end
329
+ end
330
+ end