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,310 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/models'
|
3
|
+
|
4
|
+
describe "Document" do
|
5
|
+
before do
|
6
|
+
@document = Doc do
|
7
|
+
key :first_name, String
|
8
|
+
key :last_name, String
|
9
|
+
key :age, Integer
|
10
|
+
key :date, Date
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "array key" do
|
15
|
+
before do
|
16
|
+
@document.key :tags, Array
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should give correct default" do
|
20
|
+
doc = @document.new
|
21
|
+
doc.tags.should == []
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should work with assignment" do
|
25
|
+
doc = @document.new
|
26
|
+
doc.tags = %w(foo bar)
|
27
|
+
doc.tags.should == %w(foo bar)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should work with assignment after saving" do
|
31
|
+
doc = @document.new
|
32
|
+
doc.tags = %w(foo bar)
|
33
|
+
doc.save
|
34
|
+
doc.tags.should == %w(foo bar)
|
35
|
+
doc.reload.tags.should == %w(foo bar)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should work with assignment then <<" do
|
39
|
+
doc = @document.new
|
40
|
+
doc.tags = []
|
41
|
+
doc.tags << "foo"
|
42
|
+
doc.tags.should == ["foo"]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should work with <<" do
|
46
|
+
doc = @document.new
|
47
|
+
doc.tags << "foo"
|
48
|
+
doc.tags.should == ["foo"]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should work with << then save" do
|
52
|
+
doc = @document.new
|
53
|
+
doc.tags << "foo"
|
54
|
+
doc.tags << "bar"
|
55
|
+
doc.save
|
56
|
+
doc.tags.should == %w(foo bar)
|
57
|
+
doc.reload.tags.should == %w(foo bar)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "hash key" do
|
62
|
+
before do
|
63
|
+
@document.key :foo, Hash
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should give correct default" do
|
67
|
+
doc = @document.new
|
68
|
+
doc.foo.should == {}
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should work with []=" do
|
72
|
+
doc = @document.new
|
73
|
+
doc.foo["quux"] = "bar"
|
74
|
+
doc.foo["quux"].should == "bar"
|
75
|
+
doc.foo.should == { "quux" => "bar" }
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should work with indifferent access" do
|
79
|
+
doc = @document.new
|
80
|
+
doc.foo = {:baz => 'bar'}
|
81
|
+
doc.foo[:baz].should == 'bar'
|
82
|
+
doc.foo['baz'].should == 'bar'
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should work with indifferent access after save" do
|
86
|
+
doc = @document.new
|
87
|
+
doc.foo = {:baz => 'bar'}
|
88
|
+
doc.save
|
89
|
+
|
90
|
+
doc = doc.reload
|
91
|
+
doc.foo[:baz].should == 'bar'
|
92
|
+
doc.foo['baz'].should == 'bar'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "custom type key with default" do
|
97
|
+
before do
|
98
|
+
@document.key :window, WindowSize, :default => WindowSize.new(600, 480)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should default to default" do
|
102
|
+
doc = @document.new
|
103
|
+
doc.window.should == WindowSize.new(600, 480)
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should save and load from marklogic" do
|
108
|
+
doc = @document.new
|
109
|
+
doc.save
|
110
|
+
|
111
|
+
doc = doc.reload
|
112
|
+
doc.window.should == WindowSize.new(600, 480)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "key with proc default value" do
|
117
|
+
before do
|
118
|
+
@document.key :proc_default, String, :default => lambda { return 'string' }
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should detect and run proc default" do
|
122
|
+
doc = @document.new
|
123
|
+
doc.proc_default.should == 'string'
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should save and load from marklogic" do
|
127
|
+
doc = @document.create
|
128
|
+
doc = doc.reload
|
129
|
+
doc.proc_default.should == 'string'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "symbol key" do
|
134
|
+
before do
|
135
|
+
@document.key :foo, Symbol, :default => lambda { 123 }
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should return default value" do
|
139
|
+
doc = @document.new
|
140
|
+
doc.foo.should == :'123'
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should return symbol value" do
|
144
|
+
doc = @document.create :foo => 'qwerty'
|
145
|
+
doc.foo.should == :qwerty
|
146
|
+
|
147
|
+
doc.set :foo => 'poiuyt'
|
148
|
+
doc.reload
|
149
|
+
doc.foo.should == :poiuyt
|
150
|
+
|
151
|
+
doc.foo = 'asdf'
|
152
|
+
doc.foo.should == :asdf
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should return typecasted value" do
|
156
|
+
doc = @document.new
|
157
|
+
(doc.foo = 'qwerty').should == 'qwerty'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should have instance method for collection" do
|
162
|
+
@document.new.collection.name.should == @document.collection.name
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should have instance method for database" do
|
166
|
+
@document.new.database.should == @document.database
|
167
|
+
end
|
168
|
+
|
169
|
+
context "#destroyed?" do
|
170
|
+
before do
|
171
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should be true if deleted" do
|
175
|
+
@doc1.delete
|
176
|
+
@doc1.should be_destroyed
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should be true if destroyed" do
|
180
|
+
@doc1.destroy
|
181
|
+
@doc1.should be_destroyed
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should be false if not deleted or destroyed" do
|
185
|
+
@doc1.should_not be_destroyed
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "#persisted?" do
|
190
|
+
before do
|
191
|
+
@doc = @document.new(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should be false if new" do
|
195
|
+
@doc.should_not be_persisted
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be false if destroyed" do
|
199
|
+
@doc.save
|
200
|
+
@doc.destroy
|
201
|
+
@doc.should be_destroyed
|
202
|
+
@doc.should_not be_persisted
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should be true if not new or destroyed" do
|
206
|
+
@doc.save
|
207
|
+
@doc.should be_persisted
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "#reload" do
|
212
|
+
before do
|
213
|
+
@foo_class = Doc do
|
214
|
+
key :name
|
215
|
+
end
|
216
|
+
|
217
|
+
@bar_class = EDoc do
|
218
|
+
key :name
|
219
|
+
end
|
220
|
+
|
221
|
+
@document.many :foos, :class => @foo_class
|
222
|
+
@document.many :bars, :class => @bar_class
|
223
|
+
@document.belongs_to :foo, :class => @foo_class
|
224
|
+
@document.one :bar, :class => @bar_class
|
225
|
+
|
226
|
+
@instance = @document.create({
|
227
|
+
:age => 39,
|
228
|
+
:foos => [@foo_class.new(:name => '1')],
|
229
|
+
:bars => [@bar_class.new(:name => '1')],
|
230
|
+
:foo => @foo_class.new(:name => '2'),
|
231
|
+
:bar => @bar_class.new(:name => '2')
|
232
|
+
})
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should reload keys from the database" do
|
236
|
+
@instance.age = 37
|
237
|
+
@instance.age.should == 37
|
238
|
+
@instance.reload
|
239
|
+
@instance.age.should == 39
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should reset many associations" do
|
243
|
+
expect(@instance.foos).to receive(:reset).at_least(1).times
|
244
|
+
expect(@instance.bars).to receive(:reset).at_least(1).times
|
245
|
+
@instance.reload
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should reset belongs_to association" do
|
249
|
+
@instance.foo = nil
|
250
|
+
@instance.reload
|
251
|
+
@instance.foo.should_not be_nil
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should reset one association" do
|
255
|
+
@instance.bar = nil
|
256
|
+
@instance.reload
|
257
|
+
@instance.bar.should_not be_nil
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should reset nil one association" do
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should reinstantiate embedded associations" do
|
264
|
+
@instance.reload
|
265
|
+
@instance.bars.first.name.should == '1'
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should return self" do
|
269
|
+
@instance.reload.object_id.should == @instance.object_id
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should raise DocumentNotFound if not found" do
|
273
|
+
@instance.destroy
|
274
|
+
expect { @instance.reload }.to raise_error(MarkMapper::DocumentNotFound)
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should clear keys that were removed from the database" do
|
278
|
+
@instance.unset(:age)
|
279
|
+
@instance.reload.age.should be_nil
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "database has keys not defined in model" do
|
284
|
+
before do
|
285
|
+
@id = MarkLogic::ObjectId.new
|
286
|
+
@document.collection.insert({
|
287
|
+
:_id => @id,
|
288
|
+
:first_name => 'John',
|
289
|
+
:last_name => 'Nunemaker',
|
290
|
+
:age => 27,
|
291
|
+
:favorite_color => 'red',
|
292
|
+
:skills => ['ruby', 'rails', 'javascript', 'xhtml', 'css']
|
293
|
+
})
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should assign all keys from database" do
|
297
|
+
doc = @document.find(@id)
|
298
|
+
doc.first_name.should == 'John'
|
299
|
+
doc.last_name.should == 'Nunemaker'
|
300
|
+
doc.age.should == 27
|
301
|
+
doc.favorite_color.should == 'red'
|
302
|
+
doc.skills.should == ['ruby', 'rails', 'javascript', 'xhtml', 'css']
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should not walk ObjectSpace when creating a model" do
|
307
|
+
expect(ObjectSpace).to receive(:each_object).never
|
308
|
+
Doc()
|
309
|
+
end
|
310
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache/memory_store'
|
3
|
+
|
4
|
+
describe "Documents with the Dumpable plugin" do
|
5
|
+
let(:doc) { Doc { key :foo, String } }
|
6
|
+
let(:answer) { Answer.create(:body => "answer body") }
|
7
|
+
let(:store) { ActiveSupport::Cache::MemoryStore.new(:size => 1.megabyte) }
|
8
|
+
|
9
|
+
it "should be able to be marshalled" do
|
10
|
+
expect { Marshal.dump(answer) }.to_not raise_error
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to be unmarshalled" do
|
14
|
+
dumped = Marshal.dump(answer)
|
15
|
+
reconstituted_answer = Marshal.load(dumped)
|
16
|
+
reconstituted_answer.attributes.should == answer.attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be able to be saved in a Rails cache" do
|
20
|
+
fetched = store.fetch("foo") { Answer.find(answer._id) }
|
21
|
+
fetched.body.should == "answer body"
|
22
|
+
fetched._id.should == answer._id
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Dynamic Querying" do
|
4
|
+
before do
|
5
|
+
@document = Doc do
|
6
|
+
scope :nunes, where(:last_name => 'Nunemaker')
|
7
|
+
|
8
|
+
key :first_name, String
|
9
|
+
key :last_name, String
|
10
|
+
key :age, Integer
|
11
|
+
key :date, Date
|
12
|
+
end
|
13
|
+
|
14
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => 27)
|
15
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => 28)
|
16
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => 26)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should find document based on argument" do
|
20
|
+
@document.find_by_first_name('John').should == @doc1
|
21
|
+
@document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
|
22
|
+
@document.find_by_age(27).should == @doc1
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not raise error" do
|
26
|
+
@document.find_by_first_name('MarkLogic').should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should define a method for each key" do
|
30
|
+
@document.methods(false).select { |e| e =~ /^find_by_/ }.size == @document.keys.size
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should find document based on all arguments" do
|
34
|
+
@document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not find the document if an argument is wrong" do
|
38
|
+
@document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 28).should be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should find all documents based on arguments" do
|
42
|
+
docs = @document.find_all_by_last_name('Nunemaker')
|
43
|
+
docs.should be_kind_of(Array)
|
44
|
+
docs.should include(@doc1)
|
45
|
+
docs.should include(@doc3)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should initialize document with given arguments" do
|
49
|
+
doc = @document.find_or_initialize_by_first_name_and_last_name('David', 'Cuadrado')
|
50
|
+
doc.should be_new
|
51
|
+
doc.first_name.should == 'David'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not initialize document if document is found" do
|
55
|
+
doc = @document.find_or_initialize_by_first_name('John')
|
56
|
+
doc.should_not be_new
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should create document with given arguments" do
|
60
|
+
doc = @document.find_or_create_by_first_name_and_last_name('David', 'Cuadrado')
|
61
|
+
doc.should_not be_new
|
62
|
+
doc.first_name.should == 'David'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should raise error if document is not found when using !" do
|
66
|
+
lambda {
|
67
|
+
@document.find_by_first_name_and_last_name!(1,2)
|
68
|
+
}.should raise_error(MarkMapper::DocumentNotFound)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should work on scopes" do
|
72
|
+
@document.nunes.find_by_first_name('Steph').should == @doc3
|
73
|
+
@document.nunes.find_all_by_first_name('Steph').should == [@doc3]
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,316 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/models'
|
3
|
+
|
4
|
+
describe "EmbeddedDocument" do
|
5
|
+
before do
|
6
|
+
@klass = Doc('Person') do
|
7
|
+
key :name, String
|
8
|
+
end
|
9
|
+
|
10
|
+
@pet_klass = EDoc('Pet') do
|
11
|
+
key :name, String
|
12
|
+
key :flag, Boolean
|
13
|
+
end
|
14
|
+
|
15
|
+
@klass.many :pets, :class => @pet_klass
|
16
|
+
|
17
|
+
@address_class = EDoc('Address') do
|
18
|
+
key :city, String
|
19
|
+
key :state, String
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "Saving a document with a key that is an embedded document" do
|
24
|
+
before do
|
25
|
+
@klass.key :foo, @address_class
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should embed embedded document" do
|
29
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
30
|
+
doc = @klass.create(:foo => address)
|
31
|
+
doc.foo.city.should == 'South Bend'
|
32
|
+
doc.foo.state.should == 'IN'
|
33
|
+
|
34
|
+
doc = doc.reload
|
35
|
+
doc.foo.city.should == 'South Bend'
|
36
|
+
doc.foo.state.should == 'IN'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should assign _parent_document and _root_document" do
|
40
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
41
|
+
address._parent_document.should be_nil
|
42
|
+
doc = @klass.create(:foo => address)
|
43
|
+
address._parent_document.should be(doc)
|
44
|
+
address._root_document.should be(doc)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should assign _parent_document and _root_document when loading" do
|
48
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
49
|
+
doc = @klass.create(:foo => address)
|
50
|
+
doc.reload
|
51
|
+
doc.foo._parent_document.should be(doc)
|
52
|
+
doc.foo._root_document.should be(doc)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should correctly instantiate single collection inherited embedded documents" do
|
57
|
+
document = Doc('Foo') do
|
58
|
+
key :message, Message
|
59
|
+
end
|
60
|
+
|
61
|
+
doc1 = document.create(:message => Enter.new)
|
62
|
+
doc1.reload.message.class.should be(Enter)
|
63
|
+
end
|
64
|
+
|
65
|
+
context "new? (embedded key)" do
|
66
|
+
before do
|
67
|
+
@klass.key :foo, @address_class
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be true until document is created" do
|
71
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
72
|
+
doc = @klass.new(:foo => address)
|
73
|
+
address.new?.should be_truthy
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be false after document is saved" do
|
77
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
78
|
+
doc = @klass.new(:foo => address)
|
79
|
+
doc.save
|
80
|
+
doc.foo.new?.should be_falsey
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should be false when loaded from database" do
|
84
|
+
address = @address_class.new(:city => 'South Bend', :state => 'IN')
|
85
|
+
doc = @klass.new(:foo => address)
|
86
|
+
doc.save
|
87
|
+
|
88
|
+
doc.reload
|
89
|
+
doc.foo.new?.should be_falsey
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "new? (embedded many association)" do
|
94
|
+
before do
|
95
|
+
@doc = @klass.new(:pets => [{:name => 'poo bear'}])
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should be true until document is saved" do
|
99
|
+
@doc.should be_new
|
100
|
+
@doc.pets.first.should be_new
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should be false after document is saved" do
|
104
|
+
@doc.save
|
105
|
+
@doc.pets.first.should_not be_new
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should be false when loaded from database" do
|
109
|
+
@doc.save
|
110
|
+
@doc.pets.first.should_not be_new
|
111
|
+
@doc.reload
|
112
|
+
@doc.pets.first.should_not be_new
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be true until existing document is saved" do
|
116
|
+
@doc.save
|
117
|
+
pet = @doc.pets.build(:name => 'Rasmus')
|
118
|
+
pet.new?.should be_truthy
|
119
|
+
@doc.save
|
120
|
+
pet.new?.should be_falsey
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "new? (nested embedded many association)" do
|
125
|
+
before do
|
126
|
+
@pet_klass.many :addresses, :class=> @address_class
|
127
|
+
@doc = @klass.new
|
128
|
+
@doc.pets.build(:name => 'Rasmus')
|
129
|
+
@doc.save
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should be true until existing document is saved" do
|
133
|
+
address = @doc.pets.first.addresses.build(:city => 'Holland', :state => 'MI')
|
134
|
+
address.new?.should be_truthy
|
135
|
+
@doc.save
|
136
|
+
address.new?.should be_falsey
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "new? (embedded one association)" do
|
141
|
+
before do
|
142
|
+
@klass.one :address, :class => @address_class
|
143
|
+
@doc = @klass.new
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should be true until existing document is saved" do
|
147
|
+
@doc.save
|
148
|
+
@doc.build_address(:city => 'Holland', :state => 'MI')
|
149
|
+
@doc.address.new?.should be_truthy
|
150
|
+
@doc.save
|
151
|
+
@doc.address.new?.should be_falsey
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "new? (nested embedded one association)" do
|
156
|
+
before do
|
157
|
+
@pet_klass.one :address, :class => @address_class
|
158
|
+
@doc = @klass.new
|
159
|
+
@doc.pets.build(:name => 'Rasmus')
|
160
|
+
@doc.save
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should be true until existing document is saved" do
|
164
|
+
address = @doc.pets.first.build_address(:city => 'Holland', :stats => 'MI')
|
165
|
+
address.new?.should be_truthy
|
166
|
+
@doc.save
|
167
|
+
address.new?.should be_falsey
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "#destroyed?" do
|
172
|
+
before do
|
173
|
+
@doc = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should be false if root document is not destroyed" do
|
177
|
+
@doc.should_not be_destroyed
|
178
|
+
@doc.pets.first.should_not be_destroyed
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should be true if root document is destroyed" do
|
182
|
+
@doc.destroy
|
183
|
+
@doc.should be_destroyed
|
184
|
+
@doc.pets.first.should be_destroyed
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "#persisted?" do
|
189
|
+
before do
|
190
|
+
@doc = @klass.new(:name => 'persisted doc', :pets => [@pet_klass.new(:name => 'persisted pet')])
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should be false if new" do
|
194
|
+
@doc.pets.first.should_not be_persisted
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should be false if destroyed" do
|
198
|
+
@doc.save
|
199
|
+
@doc.destroy
|
200
|
+
@doc.pets.first.should be_destroyed
|
201
|
+
@doc.pets.first.should_not be_persisted
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should be true if not new or destroyed" do
|
205
|
+
@doc.save
|
206
|
+
@doc.pets.first.should be_persisted
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should be able to save" do
|
211
|
+
person = @klass.create
|
212
|
+
|
213
|
+
pet = @pet_klass.new(:name => 'sparky')
|
214
|
+
person.pets << pet
|
215
|
+
pet.should be_new
|
216
|
+
pet.save
|
217
|
+
pet.should_not be_new
|
218
|
+
|
219
|
+
person.reload
|
220
|
+
person.pets.first.should == pet
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should be able to save!" do
|
224
|
+
person = @klass.create
|
225
|
+
|
226
|
+
pet = @pet_klass.new(:name => 'sparky')
|
227
|
+
person.pets << pet
|
228
|
+
pet.should be_new
|
229
|
+
|
230
|
+
expect(person).to receive(:save!)
|
231
|
+
pet.save!
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should be able to dynamically add new keys and save" do
|
235
|
+
person = @klass.create
|
236
|
+
|
237
|
+
pet = @pet_klass.new(:name => 'sparky', :crazy_key => 'crazy')
|
238
|
+
person.pets << pet
|
239
|
+
pet.save
|
240
|
+
|
241
|
+
person.reload
|
242
|
+
person.pets.first.crazy_key.should == 'crazy'
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should be able to update_attribute" do
|
246
|
+
pet = @pet_klass.new(:name => 'sparky')
|
247
|
+
person = @klass.create(:pets => [pet])
|
248
|
+
person.reload
|
249
|
+
pet = person.pets.first
|
250
|
+
|
251
|
+
pet.update_attribute('name', 'koda').should be_truthy
|
252
|
+
person.reload
|
253
|
+
person.pets.first._id.should == pet._id
|
254
|
+
person.pets.first.name.should == 'koda'
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should be able to update_attributes" do
|
258
|
+
pet = @pet_klass.new(:name => 'sparky')
|
259
|
+
person = @klass.create(:pets => [pet])
|
260
|
+
person.reload
|
261
|
+
pet = person.pets.first
|
262
|
+
|
263
|
+
pet.update_attributes(:name => 'koda').should be_truthy
|
264
|
+
person.reload
|
265
|
+
person.pets.first._id.should == pet._id
|
266
|
+
person.pets.first.name.should == 'koda'
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should be able to update_attributes!" do
|
270
|
+
person = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
|
271
|
+
person.reload
|
272
|
+
pet = person.pets.first
|
273
|
+
|
274
|
+
attributes = {:name => 'koda'}
|
275
|
+
expect(pet).to receive(:attributes=).with(attributes)
|
276
|
+
expect(pet).to receive(:save!)
|
277
|
+
pet.update_attributes!(attributes)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should have database instance method that is equal to root document" do
|
281
|
+
person = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
|
282
|
+
person.pets.first.database.should == person.database
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should have collection instance method that is equal to root document" do
|
286
|
+
person = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
|
287
|
+
person.pets.first.collection.name.should == person.collection.name
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should not fail if the source document contains nils in the embedded document list" do
|
291
|
+
@klass.collection.insert(:pets => [nil, {:name => "Sasha"}])
|
292
|
+
expect { @klass.all.first.pets }.to_not raise_error
|
293
|
+
@klass.all.first.pets.tap do |pets|
|
294
|
+
pets.length.should == 1
|
295
|
+
pets[0].name.should == "Sasha"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
context "Issue #536" do
|
300
|
+
it "should update attributes with string keys" do
|
301
|
+
person = @klass.create(:pets => [@pet_klass.new(:name => 'Rasmus', :flag => true)])
|
302
|
+
person.update_attributes!({"pets" => ["name" => "sparky", "flag" => "false"]})
|
303
|
+
person.reload
|
304
|
+
person.pets.first.name.should == "sparky"
|
305
|
+
person.pets.first.flag.should be_falsey
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should update attributes with symbol keys" do
|
309
|
+
person = @klass.create(:pets => [@pet_klass.new(:name => 'Rasmus', :flag => true)])
|
310
|
+
person.update_attributes!({:pets => [:name => "sparky", :flag => "false"]})
|
311
|
+
person.reload
|
312
|
+
person.pets.first.name.should == "sparky"
|
313
|
+
person.pets.first.flag.should be_falsey
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|