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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.rdoc +39 -0
- data/examples/attr_accessible.rb +24 -0
- data/examples/attr_protected.rb +24 -0
- data/examples/cache_key.rb +26 -0
- data/examples/custom_types.rb +26 -0
- data/examples/identity_map.rb +30 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +42 -0
- data/examples/modifiers/set.rb +27 -0
- data/examples/plugins.rb +40 -0
- data/examples/querying.rb +39 -0
- data/examples/sample_app.rb +43 -0
- data/examples/scopes.rb +56 -0
- data/examples/validating/embedded_docs.rb +31 -0
- data/lib/mark_mapper.rb +125 -0
- data/lib/mark_mapper/config.rb +90 -0
- data/lib/mark_mapper/connection.rb +60 -0
- data/lib/mark_mapper/criteria_hash.rb +194 -0
- data/lib/mark_mapper/document.rb +46 -0
- data/lib/mark_mapper/embedded_document.rb +32 -0
- data/lib/mark_mapper/exceptions.rb +33 -0
- data/lib/mark_mapper/extensions/array.rb +27 -0
- data/lib/mark_mapper/extensions/boolean.rb +45 -0
- data/lib/mark_mapper/extensions/date.rb +29 -0
- data/lib/mark_mapper/extensions/duplicable.rb +86 -0
- data/lib/mark_mapper/extensions/float.rb +18 -0
- data/lib/mark_mapper/extensions/hash.rb +26 -0
- data/lib/mark_mapper/extensions/integer.rb +27 -0
- data/lib/mark_mapper/extensions/kernel.rb +11 -0
- data/lib/mark_mapper/extensions/nil_class.rb +18 -0
- data/lib/mark_mapper/extensions/object.rb +30 -0
- data/lib/mark_mapper/extensions/object_id.rb +18 -0
- data/lib/mark_mapper/extensions/set.rb +20 -0
- data/lib/mark_mapper/extensions/string.rb +31 -0
- data/lib/mark_mapper/extensions/symbol.rb +87 -0
- data/lib/mark_mapper/extensions/time.rb +29 -0
- data/lib/mark_mapper/locale/en.yml +5 -0
- data/lib/mark_mapper/middleware/identity_map.rb +41 -0
- data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
- data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
- data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
- data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
- data/lib/mark_mapper/normalizers/integer.rb +19 -0
- data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
- data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
- data/lib/mark_mapper/options_hash.rb +103 -0
- data/lib/mark_mapper/pagination.rb +6 -0
- data/lib/mark_mapper/pagination/collection.rb +32 -0
- data/lib/mark_mapper/pagination/paginator.rb +46 -0
- data/lib/mark_mapper/plugins.rb +22 -0
- data/lib/mark_mapper/plugins/accessible.rb +61 -0
- data/lib/mark_mapper/plugins/active_model.rb +18 -0
- data/lib/mark_mapper/plugins/associations.rb +96 -0
- data/lib/mark_mapper/plugins/associations/base.rb +98 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
- data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
- data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
- data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mark_mapper/plugins/caching.rb +21 -0
- data/lib/mark_mapper/plugins/callbacks.rb +42 -0
- data/lib/mark_mapper/plugins/clone.rb +24 -0
- data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
- data/lib/mark_mapper/plugins/dirty.rb +61 -0
- data/lib/mark_mapper/plugins/document.rb +41 -0
- data/lib/mark_mapper/plugins/dumpable.rb +22 -0
- data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
- data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mark_mapper/plugins/equality.rb +23 -0
- data/lib/mark_mapper/plugins/identity_map.rb +144 -0
- data/lib/mark_mapper/plugins/indexable.rb +86 -0
- data/lib/mark_mapper/plugins/inspect.rb +16 -0
- data/lib/mark_mapper/plugins/keys.rb +470 -0
- data/lib/mark_mapper/plugins/keys/key.rb +134 -0
- data/lib/mark_mapper/plugins/keys/static.rb +45 -0
- data/lib/mark_mapper/plugins/logger.rb +18 -0
- data/lib/mark_mapper/plugins/modifiers.rb +140 -0
- data/lib/mark_mapper/plugins/pagination.rb +16 -0
- data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
- data/lib/mark_mapper/plugins/persistence.rb +79 -0
- data/lib/mark_mapper/plugins/protected.rb +45 -0
- data/lib/mark_mapper/plugins/querying.rb +173 -0
- data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
- data/lib/mark_mapper/plugins/rails.rb +79 -0
- data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mark_mapper/plugins/sci.rb +82 -0
- data/lib/mark_mapper/plugins/scopes.rb +28 -0
- data/lib/mark_mapper/plugins/serialization.rb +109 -0
- data/lib/mark_mapper/plugins/timestamps.rb +29 -0
- data/lib/mark_mapper/plugins/touch.rb +18 -0
- data/lib/mark_mapper/plugins/userstamps.rb +18 -0
- data/lib/mark_mapper/plugins/validations.rb +96 -0
- data/lib/mark_mapper/query.rb +278 -0
- data/lib/mark_mapper/railtie.rb +52 -0
- data/lib/mark_mapper/railtie/database.rake +65 -0
- data/lib/mark_mapper/translation.rb +10 -0
- data/lib/mark_mapper/version.rb +4 -0
- data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
- data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
- data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
- data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
- data/spec/config/mark_mapper.yml +6 -0
- data/spec/examples_spec.rb +25 -0
- data/spec/functional/accessible_spec.rb +198 -0
- data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
- data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
- data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
- data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
- data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
- data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
- data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
- data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
- data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
- data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
- data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
- data/spec/functional/associations/one_proxy_spec.rb +406 -0
- data/spec/functional/associations_spec.rb +48 -0
- data/spec/functional/caching_spec.rb +75 -0
- data/spec/functional/callbacks_spec.rb +330 -0
- data/spec/functional/counter_cache_spec.rb +235 -0
- data/spec/functional/dirty_spec.rb +316 -0
- data/spec/functional/document_spec.rb +310 -0
- data/spec/functional/dumpable_spec.rb +24 -0
- data/spec/functional/dynamic_querying_spec.rb +75 -0
- data/spec/functional/embedded_document_spec.rb +316 -0
- data/spec/functional/equality_spec.rb +20 -0
- data/spec/functional/extensions_spec.rb +16 -0
- data/spec/functional/identity_map_spec.rb +483 -0
- data/spec/functional/keys_spec.rb +339 -0
- data/spec/functional/logger_spec.rb +20 -0
- data/spec/functional/modifiers_spec.rb +446 -0
- data/spec/functional/options_hash_spec.rb +41 -0
- data/spec/functional/pagination_spec.rb +89 -0
- data/spec/functional/partial_updates_spec.rb +530 -0
- data/spec/functional/protected_spec.rb +199 -0
- data/spec/functional/querying_spec.rb +984 -0
- data/spec/functional/rails_spec.rb +55 -0
- data/spec/functional/sci_spec.rb +374 -0
- data/spec/functional/scopes_spec.rb +204 -0
- data/spec/functional/static_keys_spec.rb +153 -0
- data/spec/functional/timestamps_spec.rb +97 -0
- data/spec/functional/touch_spec.rb +125 -0
- data/spec/functional/userstamps_spec.rb +46 -0
- data/spec/functional/validations_spec.rb +416 -0
- data/spec/quality_spec.rb +51 -0
- data/spec/spec_helper.rb +150 -0
- data/spec/support/matchers.rb +15 -0
- data/spec/support/models.rb +256 -0
- data/spec/symbol_operator_spec.rb +70 -0
- data/spec/symbol_spec.rb +9 -0
- data/spec/unit/associations/base_spec.rb +146 -0
- data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
- data/spec/unit/associations/many_association_spec.rb +64 -0
- data/spec/unit/associations/one_association_spec.rb +48 -0
- data/spec/unit/associations/proxy_spec.rb +103 -0
- data/spec/unit/clone_spec.rb +79 -0
- data/spec/unit/config_generator_spec.rb +24 -0
- data/spec/unit/criteria_hash_spec.rb +218 -0
- data/spec/unit/document_spec.rb +251 -0
- data/spec/unit/dynamic_finder_spec.rb +125 -0
- data/spec/unit/embedded_document_spec.rb +676 -0
- data/spec/unit/equality_spec.rb +38 -0
- data/spec/unit/exceptions_spec.rb +12 -0
- data/spec/unit/extensions_spec.rb +368 -0
- data/spec/unit/identity_map_middleware_spec.rb +134 -0
- data/spec/unit/inspect_spec.rb +47 -0
- data/spec/unit/key_spec.rb +276 -0
- data/spec/unit/keys_spec.rb +155 -0
- data/spec/unit/mark_mapper_spec.rb +37 -0
- data/spec/unit/model_generator_spec.rb +45 -0
- data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
- data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
- data/spec/unit/normalizers/fields_value_spec.rb +45 -0
- data/spec/unit/normalizers/hash_key_spec.rb +15 -0
- data/spec/unit/normalizers/integer_spec.rb +24 -0
- data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
- data/spec/unit/normalizers/sort_value_spec.rb +98 -0
- data/spec/unit/options_hash_spec.rb +64 -0
- data/spec/unit/pagination/collection_spec.rb +30 -0
- data/spec/unit/pagination/paginator_spec.rb +118 -0
- data/spec/unit/pagination_spec.rb +11 -0
- data/spec/unit/plugins_spec.rb +89 -0
- data/spec/unit/query_spec.rb +837 -0
- data/spec/unit/rails_compatibility_spec.rb +40 -0
- data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
- data/spec/unit/rails_spec.rb +188 -0
- data/spec/unit/serialization_spec.rb +169 -0
- data/spec/unit/serializers/json_serializer_spec.rb +218 -0
- data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
- data/spec/unit/time_zones_spec.rb +44 -0
- data/spec/unit/translation_spec.rb +27 -0
- data/spec/unit/validations_spec.rb +588 -0
- metadata +307 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CounterCacheFixtureModels
|
4
|
+
class User
|
5
|
+
include MarkMapper::Document
|
6
|
+
|
7
|
+
key :posts_count, Integer, :default => 0
|
8
|
+
|
9
|
+
has_many :posts,
|
10
|
+
:class_name => "CounterCacheFixtureModels::Post"
|
11
|
+
end
|
12
|
+
|
13
|
+
class Post
|
14
|
+
include MarkMapper::Document
|
15
|
+
|
16
|
+
key :comments_count, Integer, :default => 0
|
17
|
+
key :some_custom_comments_count, Integer, :default => 0
|
18
|
+
key :commentable_count, Integer, :default => 0
|
19
|
+
|
20
|
+
has_many :comments,
|
21
|
+
:class_name => "CounterCacheFixtureModels::Comment"
|
22
|
+
|
23
|
+
belongs_to :user,
|
24
|
+
:counter_cache => true,
|
25
|
+
:class_name => "CounterCacheFixtureModels::User"
|
26
|
+
|
27
|
+
many :polymorphic_comments,
|
28
|
+
:as => :commentable,
|
29
|
+
:class_name => "CounterCacheFixtureModels::Comment"
|
30
|
+
end
|
31
|
+
|
32
|
+
class Article
|
33
|
+
include MarkMapper::Document
|
34
|
+
|
35
|
+
key :commentable_count, Integer, :default => 0
|
36
|
+
|
37
|
+
many :polymorphic_comments,
|
38
|
+
:as => :commentable,
|
39
|
+
:class_name => "CounterCacheFixtureModels::Comment"
|
40
|
+
end
|
41
|
+
|
42
|
+
class Comment
|
43
|
+
include MarkMapper::Document
|
44
|
+
|
45
|
+
belongs_to :post,
|
46
|
+
:counter_cache => true,
|
47
|
+
:class_name => "CounterCacheFixtureModels::Post"
|
48
|
+
|
49
|
+
belongs_to :commentable,
|
50
|
+
:polymorphic => true,
|
51
|
+
:counter_cache => :commentable_count
|
52
|
+
end
|
53
|
+
|
54
|
+
class CustomComment
|
55
|
+
include MarkMapper::Document
|
56
|
+
|
57
|
+
belongs_to :post,
|
58
|
+
:counter_cache => :some_custom_comments_count,
|
59
|
+
:class_name => "CounterCacheFixtureModels::Post"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe MarkMapper::Plugins::CounterCache do
|
64
|
+
before do
|
65
|
+
@post_class = CounterCacheFixtureModels::Post
|
66
|
+
@comment_class = CounterCacheFixtureModels::Comment
|
67
|
+
@user_class = CounterCacheFixtureModels::User
|
68
|
+
@custom_comment_class = CounterCacheFixtureModels::CustomComment
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should have a key with posts_count defaulting to 0" do
|
72
|
+
@post_class.new.comments_count.should == 0
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should update the count when a new object is created" do
|
76
|
+
post = @post_class.new
|
77
|
+
comment = @comment_class.new
|
78
|
+
|
79
|
+
post.save!
|
80
|
+
|
81
|
+
comment.post = post
|
82
|
+
comment.save!
|
83
|
+
|
84
|
+
post.reload
|
85
|
+
post.comments_count.should == 1
|
86
|
+
|
87
|
+
second_comment = @comment_class.new
|
88
|
+
second_comment.post = post
|
89
|
+
second_comment.save!
|
90
|
+
|
91
|
+
post.reload
|
92
|
+
post.comments_count.should == 2
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should decrease the count by one when an object is destroyed" do
|
96
|
+
post = @post_class.new
|
97
|
+
comment = @comment_class.new
|
98
|
+
|
99
|
+
post.save!
|
100
|
+
|
101
|
+
comment.post = post
|
102
|
+
comment.save!
|
103
|
+
|
104
|
+
post.reload
|
105
|
+
post.comments_count.should == 1
|
106
|
+
|
107
|
+
comment.destroy
|
108
|
+
post.reload
|
109
|
+
post.comments_count.should == 0
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should use the correct association name" do
|
113
|
+
@user = @user_class.new
|
114
|
+
@post = @post_class.new
|
115
|
+
|
116
|
+
@user.save!
|
117
|
+
@post.user = @user
|
118
|
+
@post.save!
|
119
|
+
|
120
|
+
@user.reload
|
121
|
+
@user.posts_count.should == 1
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should be able to use a custom field name" do
|
125
|
+
@post = @post_class.new
|
126
|
+
@custom_comment = @custom_comment_class.new
|
127
|
+
|
128
|
+
@post.save!
|
129
|
+
@custom_comment.post = @post
|
130
|
+
@custom_comment.save!
|
131
|
+
|
132
|
+
@post.reload
|
133
|
+
@post.some_custom_comments_count.should == 1
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should thrown an error if there is no association" do
|
137
|
+
lambda {
|
138
|
+
CounterCacheFixtureModels.module_eval do
|
139
|
+
class CommentWithInvalidAssociation
|
140
|
+
include MarkMapper::Document
|
141
|
+
|
142
|
+
belongs_to :post,
|
143
|
+
:class_name => "CounterCacheFixtureModels::Post"
|
144
|
+
|
145
|
+
counter_cache :foo
|
146
|
+
end
|
147
|
+
end
|
148
|
+
}.should raise_error(MarkMapper::Plugins::CounterCache::InvalidCounterCacheError, "You must define an association with name `foo' on model CommentWithInvalidAssociation")
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should thown a sensible error if the field is not defined on the target object" do
|
152
|
+
lambda {
|
153
|
+
CounterCacheFixtureModels.module_eval do
|
154
|
+
class CommentWithBadRefenceField
|
155
|
+
include MarkMapper::Document
|
156
|
+
|
157
|
+
belongs_to :post,
|
158
|
+
:class_name => "CounterCacheFixtureModels::Post"
|
159
|
+
|
160
|
+
counter_cache :post, :field => :invalid_field
|
161
|
+
end
|
162
|
+
end
|
163
|
+
}.should raise_error(MarkMapper::Plugins::CounterCache::InvalidCounterCacheError, "Missing `key :invalid_field, Integer, :default => 0' on model CounterCacheFixtureModels::Post")
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "with polymorphic associations" do
|
167
|
+
before do
|
168
|
+
@article = CounterCacheFixtureModels::Article.new
|
169
|
+
@comment = CounterCacheFixtureModels::Comment.new
|
170
|
+
@comment.commentable = @article
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should update the counter cache on save" do
|
174
|
+
expect {
|
175
|
+
@comment.save!
|
176
|
+
@article.reload
|
177
|
+
}.to change(@article, :commentable_count).by(1)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should increment with a second object" do
|
181
|
+
@comment.save!
|
182
|
+
|
183
|
+
expect {
|
184
|
+
second_comment = CounterCacheFixtureModels::Comment.new
|
185
|
+
second_comment.commentable = @article
|
186
|
+
second_comment.save!
|
187
|
+
@article.reload
|
188
|
+
}.to change(@article, :commentable_count).by(1)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should decrement the counter cache on destroy" do
|
192
|
+
@comment.save!
|
193
|
+
|
194
|
+
expect {
|
195
|
+
@comment.destroy
|
196
|
+
@article.reload
|
197
|
+
}.to change(@article, :commentable_count).by(-1)
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should increment with a different type of object" do
|
201
|
+
@comment.save!
|
202
|
+
|
203
|
+
expect {
|
204
|
+
second_comment = CounterCacheFixtureModels::Comment.new
|
205
|
+
second_comment.commentable = @article
|
206
|
+
second_comment.save!
|
207
|
+
|
208
|
+
@article.reload
|
209
|
+
}.to change(@article, :commentable_count).by(1)
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "without a counter cache field" do
|
213
|
+
before do
|
214
|
+
@comment = CounterCacheFixtureModels::Comment.new
|
215
|
+
@klass = Class.new do
|
216
|
+
include MarkMapper::Document
|
217
|
+
|
218
|
+
many :polymorphic_comments,
|
219
|
+
:as => :commentable,
|
220
|
+
:class_name => "CounterCacheFixtureModels::Comment"
|
221
|
+
end
|
222
|
+
|
223
|
+
@obj = @klass.new
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should raise at save (runtime) if there is no counter cache field" do
|
227
|
+
@comment.commentable = @obj
|
228
|
+
|
229
|
+
expect {
|
230
|
+
@comment.save!
|
231
|
+
}.to raise_error(MarkMapper::Plugins::CounterCache::InvalidCounterCacheError)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,316 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Dirty" do
|
4
|
+
before do
|
5
|
+
@document = Doc {
|
6
|
+
key :phrase, String
|
7
|
+
key :paragraph, String, :alias => :para
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
context "marking changes" do
|
12
|
+
it "should not happen if there are none" do
|
13
|
+
doc = @document.new
|
14
|
+
doc.phrase_changed?.should be_falsey
|
15
|
+
doc.phrase_change.should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should happen when change happens" do
|
19
|
+
doc = @document.new
|
20
|
+
doc.phrase = 'Golly Gee Willikers Batman'
|
21
|
+
doc.phrase_changed?.should be_truthy
|
22
|
+
doc.phrase_was.should be_nil
|
23
|
+
doc.phrase_change.should == [nil, 'Golly Gee Willikers Batman']
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should happen when initializing" do
|
27
|
+
doc = @document.new(:phrase => 'Foo')
|
28
|
+
doc.changed?.should be_truthy
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should clear changes on save" do
|
32
|
+
doc = @document.new
|
33
|
+
doc.phrase = 'Golly Gee Willikers Batman'
|
34
|
+
doc.phrase_changed?.should be_truthy
|
35
|
+
doc.save
|
36
|
+
doc.phrase_changed?.should_not be_truthy
|
37
|
+
doc.phrase_change.should be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should clear changes on save!" do
|
41
|
+
doc = @document.new
|
42
|
+
doc.phrase = 'Golly Gee Willikers Batman'
|
43
|
+
doc.phrase_changed?.should be_truthy
|
44
|
+
doc.save!
|
45
|
+
doc.phrase_changed?.should_not be_truthy
|
46
|
+
doc.phrase_change.should be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not happen when loading from database" do
|
50
|
+
doc = @document.create(:phrase => 'Foo')
|
51
|
+
expect_any_instance_of(@document).to receive(:attribute_will_change!).never
|
52
|
+
expect_any_instance_of(@document).to receive(:attribute_changed?).never
|
53
|
+
doc = @document.find(doc.id)
|
54
|
+
doc.changed?.should be_falsey
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not happen when reloading from database" do
|
58
|
+
doc = @document.create(:phrase => 'Foo')
|
59
|
+
doc = @document.find(doc.id)
|
60
|
+
|
61
|
+
doc.changed?.should be_falsey
|
62
|
+
doc.phrase = 'Fart'
|
63
|
+
doc.changed?.should be_truthy
|
64
|
+
doc.reload
|
65
|
+
doc.changed?.should be_falsey
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should happen if changed after loading from database" do
|
69
|
+
doc = @document.create(:phrase => 'Foo')
|
70
|
+
doc.reload
|
71
|
+
doc.changed?.should be_falsey
|
72
|
+
doc.phrase = 'Bar'
|
73
|
+
doc.changed?.should be_truthy
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should happen with aliased keys" do
|
77
|
+
doc = @document.create(:paragraph => 'Wibbly')
|
78
|
+
doc.paragraph = "Wobbly"
|
79
|
+
doc.changed?.should be_truthy
|
80
|
+
doc.paragraph_changed?.should be_truthy
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "blank new value and type integer" do
|
85
|
+
it "should not mark changes" do
|
86
|
+
@document.key :age, Integer
|
87
|
+
|
88
|
+
[nil, ''].each do |value|
|
89
|
+
doc = @document.new
|
90
|
+
doc.age = value
|
91
|
+
doc.age_changed?.should be_falsey
|
92
|
+
doc.age_change.should be_nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "blank new value and type float" do
|
98
|
+
it "should not mark changes" do
|
99
|
+
@document.key :amount, Float
|
100
|
+
|
101
|
+
[nil, ''].each do |value|
|
102
|
+
doc = @document.new
|
103
|
+
doc.amount = value
|
104
|
+
doc.amount_changed?.should be_falsey
|
105
|
+
doc.amount_change.should be_nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "changed?" do
|
111
|
+
it "should be true if key changed" do
|
112
|
+
doc = @document.new
|
113
|
+
doc.phrase = 'A penny saved is a penny earned.'
|
114
|
+
doc.changed?.should be_truthy
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should be false if no keys changed" do
|
118
|
+
@document.new.changed?.should be_falsey
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not raise when key name is 'value'" do
|
122
|
+
@document.key :value, Integer
|
123
|
+
|
124
|
+
doc = @document.new
|
125
|
+
doc.value_changed?.should be_falsey
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should be false if the same ObjectId was assigned in String format" do
|
129
|
+
@document.key :doc_id, ObjectId
|
130
|
+
|
131
|
+
doc = @document.create!(:doc_id => MarkLogic::ObjectId.new)
|
132
|
+
doc.changed?.should be_falsey
|
133
|
+
doc.doc_id = doc.doc_id.to_s
|
134
|
+
doc.changed?.should be_falsey
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "changes" do
|
139
|
+
it "should be empty hash if no changes" do
|
140
|
+
@document.new.changes.should == {}
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should be hash of keys with values of changes if there are changes" do
|
144
|
+
doc = @document.new
|
145
|
+
doc.phrase = 'A penny saved is a penny earned.'
|
146
|
+
doc.changes['phrase'].should == [nil, 'A penny saved is a penny earned.']
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "changed" do
|
151
|
+
it "should be empty array if no changes" do
|
152
|
+
@document.new.changed.should == []
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be array of keys that have changed if there are changes" do
|
156
|
+
doc = @document.new
|
157
|
+
doc.phrase = 'A penny saved is a penny earned.'
|
158
|
+
doc.changed.should == ['phrase']
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "will_change!" do
|
163
|
+
it "should mark changes" do
|
164
|
+
doc = @document.create(:phrase => 'Foo')
|
165
|
+
|
166
|
+
doc.phrase << 'bar'
|
167
|
+
doc.phrase_changed?.should be_falsey
|
168
|
+
|
169
|
+
doc.phrase_will_change!
|
170
|
+
doc.phrase_changed?.should be_truthy
|
171
|
+
doc.phrase_change.should == ['Foobar', 'Foobar']
|
172
|
+
|
173
|
+
doc.phrase << '!'
|
174
|
+
doc.phrase_changed?.should be_truthy
|
175
|
+
doc.phrase_change.should == ['Foobar', 'Foobar!']
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "changing a foreign key through association" do
|
180
|
+
it "should mark changes" do
|
181
|
+
project_class = Doc do
|
182
|
+
key :name, String
|
183
|
+
end
|
184
|
+
|
185
|
+
milestone_class = Doc do
|
186
|
+
key :project_id, ObjectId
|
187
|
+
key :name, String
|
188
|
+
end
|
189
|
+
milestone_class.belongs_to :project, :class => project_class
|
190
|
+
|
191
|
+
milestone = milestone_class.create(:name => 'Launch')
|
192
|
+
milestone.project = project_class.create(:name => 'Harmony')
|
193
|
+
milestone.changed?.should be_truthy
|
194
|
+
milestone.changed.should == %w(project_id)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "save with an invalid document" do
|
199
|
+
it "should not clear changes" do
|
200
|
+
validated_class = Doc do
|
201
|
+
key :name, String
|
202
|
+
key :required, String, :required=>true
|
203
|
+
end
|
204
|
+
validated_doc = validated_class.new
|
205
|
+
validated_doc.name = "I'm a changin"
|
206
|
+
validated_doc.save
|
207
|
+
validated_doc.changed?.should be_truthy
|
208
|
+
|
209
|
+
validated_doc.required = 1
|
210
|
+
validated_doc.save
|
211
|
+
validated_doc.changed?.should be_falsey
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "changing an already changed attribute" do
|
216
|
+
it "should preserve the original value" do
|
217
|
+
doc = @document.create(:a=>"b")
|
218
|
+
doc.a = "c"
|
219
|
+
doc.a_change.should == ["b","c"]
|
220
|
+
doc.a = "d"
|
221
|
+
doc.a_change.should == ["b","d"]
|
222
|
+
end
|
223
|
+
it "should reset changes when set back to the original value" do
|
224
|
+
doc = @document.create(:a=>"b")
|
225
|
+
doc.a = "c"
|
226
|
+
doc.a = "b"
|
227
|
+
doc.changed?.should be_falsey
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "reset_attribute!" do
|
232
|
+
it "should reset the attribute back to the previous value" do
|
233
|
+
doc = @document.create(:a=>"b")
|
234
|
+
doc.a = "c"
|
235
|
+
doc.reset_a!
|
236
|
+
doc.changed?.should be_falsey
|
237
|
+
doc.a.should == "b"
|
238
|
+
end
|
239
|
+
it "should reset the attribute back to the original value after several changes" do
|
240
|
+
doc = @document.create(:a=>"b")
|
241
|
+
doc.a = "c"
|
242
|
+
doc.a = "d"
|
243
|
+
doc.a = "e"
|
244
|
+
doc.reset_a!
|
245
|
+
doc.changed?.should be_falsey
|
246
|
+
doc.a.should == "b"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context "previous_changes" do
|
251
|
+
it "should reflect previously committed change" do
|
252
|
+
doc = @document.create(:a=>"b")
|
253
|
+
doc.a = "c"
|
254
|
+
changes = doc.changes
|
255
|
+
doc.save!
|
256
|
+
doc.previous_changes.should == changes
|
257
|
+
doc.previous_changes["a"].should == ["b", "c"]
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should not include attributes loaded from db" do
|
261
|
+
doc = @document.create(:a => "b")
|
262
|
+
@document.find(doc.id).previous_changes.should be_blank
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "Embedded documents" do
|
267
|
+
before do
|
268
|
+
@edoc = EDoc('Duck') { key :name, String }
|
269
|
+
@edoc.plugin MarkMapper::Plugins::Dirty
|
270
|
+
@document = Doc('Long') { key :name, String }
|
271
|
+
@document.many :ducks, :class=>@edoc
|
272
|
+
@doc = @document.new
|
273
|
+
@duck = @doc.ducks.build
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should track changes" do
|
277
|
+
@duck.name = "hi"
|
278
|
+
@duck.changed?.should be_truthy
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should clear changes when saved" do
|
282
|
+
@duck.name = "hi"
|
283
|
+
@duck.changed?.should be_truthy
|
284
|
+
@duck.save!
|
285
|
+
@duck.changed?.should_not be_truthy
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should clear changes when the parent is saved" do
|
289
|
+
@duck.name = "hi"
|
290
|
+
@duck.changed?.should be_truthy
|
291
|
+
@doc.save!
|
292
|
+
@duck.changed?.should_not be_truthy
|
293
|
+
end
|
294
|
+
|
295
|
+
context "with nested embedded documents" do
|
296
|
+
before do
|
297
|
+
@inner_edoc = EDoc('Dong') {key :name, String}
|
298
|
+
@inner_edoc.plugin MarkMapper::Plugins::Dirty
|
299
|
+
@edoc.many :dongs, :class=>@inner_edoc
|
300
|
+
@dong = @duck.dongs.build
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should track changes" do
|
304
|
+
@dong.name = "hi"
|
305
|
+
@dong.changed?.should be_truthy
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should clear changes when the root saves" do
|
309
|
+
@dong.name = "hi"
|
310
|
+
@dong.changed?.should be_truthy
|
311
|
+
@doc.save!
|
312
|
+
@dong.changed?.should be_falsey
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|