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,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MarkMapper::OptionsHash do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
describe "#[]=" do
|
7
|
+
it "changes order to sort" do
|
8
|
+
subject[:order] = "foo asc"
|
9
|
+
subject[:sort].should == [["foo", 1]]
|
10
|
+
subject[:order].should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "changes sort(id) to sort(_id)" do
|
14
|
+
subject[:sort] = "id asc"
|
15
|
+
subject[:sort].should == [["_id", 1]]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "changes select to fields" do
|
19
|
+
subject[:select] = [:foo]
|
20
|
+
subject[:fields].should == [:foo]
|
21
|
+
subject[:select].should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "changes offset to skip" do
|
25
|
+
subject[:offset] = 10
|
26
|
+
subject[:skip].should == 10
|
27
|
+
subject[:offset].should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "changes id to _id" do
|
31
|
+
subject[:id] = :foo
|
32
|
+
subject[:_id].should == :foo
|
33
|
+
subject[:id].should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it "does not change the sort field" do
|
37
|
+
subject[:order] = :order.asc
|
38
|
+
subject[:sort].should == [["order", 1]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Pagination" do
|
4
|
+
before do
|
5
|
+
@document = Doc do
|
6
|
+
key :first_name, String
|
7
|
+
key :last_name, String
|
8
|
+
key :age, Integer
|
9
|
+
|
10
|
+
def self.per_page; 1 end
|
11
|
+
end
|
12
|
+
|
13
|
+
@doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
|
14
|
+
@doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
|
15
|
+
@doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return the total pages" do
|
19
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
20
|
+
result.total_pages.should == 2
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return the total pages when defaulting to the document class per_page" do
|
24
|
+
result = @document.paginate(:page => 1)
|
25
|
+
result.total_pages.should == 3
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the total of records" do
|
29
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
30
|
+
result.total_entries.should == 3
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the items" do
|
34
|
+
result = @document.paginate(:per_page => 2, :page => 1, :order => 'first_name')
|
35
|
+
result.size.should == 2
|
36
|
+
result.should == [@doc1, @doc3]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should accept conditions" do
|
40
|
+
result = @document.paginate({
|
41
|
+
:last_name => 'Nunemaker',
|
42
|
+
:order => "age DESC",
|
43
|
+
:per_page => 2,
|
44
|
+
:page => 1,
|
45
|
+
})
|
46
|
+
result.should == [@doc1, @doc3]
|
47
|
+
result.first.age.should == 27
|
48
|
+
|
49
|
+
result = @document.paginate({
|
50
|
+
:conditions => {:last_name => 'Nunemaker'},
|
51
|
+
:order => "age DESC",
|
52
|
+
:per_page => 2,
|
53
|
+
:page => 1} )
|
54
|
+
result.should == [@doc1, @doc3]
|
55
|
+
result.first.age.should == 27
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should withstand rigor" do
|
59
|
+
result = @document.paginate({
|
60
|
+
:per_page => 1,
|
61
|
+
:page => 1,
|
62
|
+
:order => 'age desc',
|
63
|
+
:last_name => 'Nunemaker'
|
64
|
+
})
|
65
|
+
result.should == [@doc1]
|
66
|
+
result.total_entries.should == 2
|
67
|
+
result.total_pages.should == 2
|
68
|
+
|
69
|
+
result = @document.paginate({
|
70
|
+
:per_page => 1,
|
71
|
+
:page => 2,
|
72
|
+
:order => 'age desc',
|
73
|
+
:last_name => 'Nunemaker'
|
74
|
+
})
|
75
|
+
result.should == [@doc3]
|
76
|
+
result.total_entries.should == 2
|
77
|
+
result.total_pages.should == 2
|
78
|
+
|
79
|
+
result = @document.paginate({
|
80
|
+
:per_page => 2,
|
81
|
+
:page => 1,
|
82
|
+
:order => 'age desc',
|
83
|
+
:last_name => 'Nunemaker'
|
84
|
+
})
|
85
|
+
result.should == [@doc1, @doc3]
|
86
|
+
result.total_entries.should == 2
|
87
|
+
result.total_pages.should == 1
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,530 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Partial Updates" do
|
4
|
+
before do
|
5
|
+
@klass = Doc("PartialUpdates") do
|
6
|
+
key :string_field, String
|
7
|
+
key :array_field, Array
|
8
|
+
key :hash_field, Hash
|
9
|
+
key :integer_field, Integer
|
10
|
+
|
11
|
+
timestamps!
|
12
|
+
end
|
13
|
+
|
14
|
+
@dealiased_keys_class = Doc("DealiasedKeys") do
|
15
|
+
key :foo, :abbr => "f"
|
16
|
+
end
|
17
|
+
|
18
|
+
@pet_klass = EDoc('Pet') do
|
19
|
+
key :name, String
|
20
|
+
key :flag, Boolean
|
21
|
+
end
|
22
|
+
|
23
|
+
@person_class = Doc('Person') do
|
24
|
+
key :name, String
|
25
|
+
end
|
26
|
+
@person_class.many :pets, :class => @pet_klass
|
27
|
+
|
28
|
+
@author_class = Doc("Author")
|
29
|
+
|
30
|
+
@post_class = Doc("Post") do
|
31
|
+
key :title, String
|
32
|
+
end
|
33
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :nullify
|
34
|
+
|
35
|
+
@comments_class = Doc("Comment") do
|
36
|
+
key :text, String
|
37
|
+
key :owner_id, ObjectId
|
38
|
+
end
|
39
|
+
|
40
|
+
@klass.partial_updates = true
|
41
|
+
@dealiased_keys_class.partial_updates = true
|
42
|
+
@person_class.partial_updates = true
|
43
|
+
@post_class.partial_updates = true
|
44
|
+
@author_class.partial_updates = true
|
45
|
+
@comments_class.partial_updates = true
|
46
|
+
|
47
|
+
@obj = @klass.new
|
48
|
+
end
|
49
|
+
|
50
|
+
after do
|
51
|
+
@klass.destroy_all
|
52
|
+
@dealiased_keys_class.destroy_all
|
53
|
+
@person_class.destroy_all
|
54
|
+
@author_class.destroy_all
|
55
|
+
@post_class.destroy_all
|
56
|
+
@comments_class.destroy_all
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be able to turn on and off partial updates for the klass" do
|
60
|
+
@klass.partial_updates = false
|
61
|
+
@klass.partial_updates.should be_falsey
|
62
|
+
|
63
|
+
@klass.partial_updates = true
|
64
|
+
@klass.partial_updates.should be_truthy
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have partial updates off by default" do
|
68
|
+
Doc {}.partial_updates.should be_falsey
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should update fields" do
|
72
|
+
@obj.string_field = "foo"
|
73
|
+
@obj.string_field.should == "foo"
|
74
|
+
@obj.save!
|
75
|
+
|
76
|
+
@obj.string_field = "bar"
|
77
|
+
@obj.string_field.should == "bar"
|
78
|
+
@obj.save!
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "with partial updates on" do
|
82
|
+
it "should only update fields that have changed on save" do
|
83
|
+
@obj.string_field = "foo"
|
84
|
+
@obj.save!
|
85
|
+
|
86
|
+
mock_collection = double 'collection'
|
87
|
+
allow(@obj).to receive(:collection).and_return mock_collection
|
88
|
+
|
89
|
+
expect(@obj.collection).to receive(:update).with({:_id => @obj.id}, {
|
90
|
+
'$set' => {
|
91
|
+
"string_field" => "bar",
|
92
|
+
"updated_at" => kind_of(Time)
|
93
|
+
}
|
94
|
+
})
|
95
|
+
|
96
|
+
@obj.string_field = "bar"
|
97
|
+
@obj.save!
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should properly nullify associations" do
|
101
|
+
@post = @post_class.create
|
102
|
+
@author = @author_class.new
|
103
|
+
@post.author = @author
|
104
|
+
@author.reload
|
105
|
+
@author.authorable_id.should == @post.id
|
106
|
+
|
107
|
+
@post.author = @author_class.new
|
108
|
+
|
109
|
+
@author.reload
|
110
|
+
@author.authorable_id.should be_nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "when partial updates are off" do
|
115
|
+
before do
|
116
|
+
@klass.partial_updates = false
|
117
|
+
@obj = @klass.new
|
118
|
+
|
119
|
+
@post_class.partial_updates = false
|
120
|
+
@author_class.partial_updates = false
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should update all attributes" do
|
124
|
+
@obj.string_field = "foo"
|
125
|
+
@obj.save!
|
126
|
+
|
127
|
+
mock_collection = double 'collection'
|
128
|
+
allow(@obj).to receive(:collection).and_return mock_collection
|
129
|
+
|
130
|
+
expect(@obj.collection).to receive(:save).with({
|
131
|
+
"_id" => @obj.id,
|
132
|
+
"string_field" => "bar",
|
133
|
+
"array_field" => [],
|
134
|
+
"hash_field" => {},
|
135
|
+
"created_at" => kind_of(Time),
|
136
|
+
"updated_at" => kind_of(Time),
|
137
|
+
})
|
138
|
+
|
139
|
+
@obj.string_field = "bar"
|
140
|
+
@obj.save!
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should raise if fields_for_partial_update is called" do
|
144
|
+
lambda {
|
145
|
+
@obj.fields_for_partial_update
|
146
|
+
}.should raise_error(MarkMapper::Plugins::PartialUpdates::PartialUpdatesDisabledError)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should properly nullify associations" do
|
150
|
+
@post = @post_class.create
|
151
|
+
@author = @author_class.new
|
152
|
+
@post.author = @author
|
153
|
+
@author.reload
|
154
|
+
@author.authorable_id.should == @post.id
|
155
|
+
|
156
|
+
@post.author = @author_class.new
|
157
|
+
|
158
|
+
@author.reload
|
159
|
+
@author.authorable_id.should be_nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "detecting attribute changes" do
|
164
|
+
it "should be able to find the fields_for_partial_update" do
|
165
|
+
@obj.string_field = "foo"
|
166
|
+
|
167
|
+
fields_for_partial_updates = @obj.fields_for_partial_update
|
168
|
+
fields_for_partial_updates.keys.should =~ [:set_fields, :unset_fields]
|
169
|
+
fields_for_partial_updates[:set_fields].should =~ ["_id", "string_field"]
|
170
|
+
fields_for_partial_updates[:unset_fields] == []
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should not find any if no fields have changed" do
|
174
|
+
@obj.save!
|
175
|
+
@obj.fields_for_partial_update.should == {
|
176
|
+
:set_fields => [],
|
177
|
+
:unset_fields => []
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should be cleared after save" do
|
182
|
+
@obj.string_field = "foo"
|
183
|
+
@obj.fields_for_partial_update[:set_fields].should =~ ["_id", "string_field"]
|
184
|
+
|
185
|
+
@obj.save!
|
186
|
+
|
187
|
+
@obj.fields_for_partial_update.should == {
|
188
|
+
:set_fields => [],
|
189
|
+
:unset_fields => []
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should detect in place updates with a string" do
|
194
|
+
@obj.string_field = "foo"
|
195
|
+
@obj.save!
|
196
|
+
|
197
|
+
@obj.string_field.gsub!(/foo/, "bar")
|
198
|
+
@obj.string_field.should == "bar"
|
199
|
+
@obj.fields_for_partial_update[:set_fields].should == ["string_field"]
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should detect in place updates with an array" do
|
203
|
+
@obj.array_field = [1]
|
204
|
+
@obj.save!
|
205
|
+
|
206
|
+
@obj.array_field << 2
|
207
|
+
@obj.array_field.should == [1,2]
|
208
|
+
@obj.fields_for_partial_update[:set_fields].should == ["array_field"]
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should detect non-key based values" do
|
212
|
+
@obj.attributes = { :non_keyed_field => "foo" }
|
213
|
+
@obj.fields_for_partial_update[:set_fields].should =~ ["_id", "non_keyed_field"]
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should allow fields that have numbers to be changed" do
|
217
|
+
@obj.integer_field = 1
|
218
|
+
@obj.save!
|
219
|
+
|
220
|
+
@obj.integer_field = 2
|
221
|
+
@obj.fields_for_partial_update[:set_fields].should == ["integer_field"]
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should update fields with dealiased keys" do
|
225
|
+
@obj = @dealiased_keys_class.new(:foo => "one")
|
226
|
+
@obj.fields_for_partial_update[:set_fields].should =~ ["_id", "f"]
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should update fields that have been deleted" do
|
230
|
+
@obj.attributes = { :foo => "bar" }
|
231
|
+
@obj.save!
|
232
|
+
|
233
|
+
attrs = @obj.attributes.dup
|
234
|
+
attrs.delete("foo")
|
235
|
+
|
236
|
+
allow(@obj).to receive(:attributes).and_return(attrs)
|
237
|
+
|
238
|
+
@obj.fields_for_partial_update.should == {
|
239
|
+
:set_fields => [],
|
240
|
+
:unset_fields => ["foo"]
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should have an empty list of fields_for_partial_update[:set_fields] after reload" do
|
245
|
+
@obj.integer_field = 10
|
246
|
+
@obj.save!
|
247
|
+
|
248
|
+
@obj.reload
|
249
|
+
@obj.fields_for_partial_update.should == {
|
250
|
+
:set_fields => [],
|
251
|
+
:unset_fields => []
|
252
|
+
}
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should return [] when re-found with find()" do
|
256
|
+
@obj.save!
|
257
|
+
obj_refound = @klass.find(@obj.id)
|
258
|
+
obj_refound.fields_for_partial_update.should == {
|
259
|
+
:set_fields => [],
|
260
|
+
:unset_fields => []
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should return a field when re-found with find() and changed" do
|
265
|
+
@obj.save!
|
266
|
+
obj_refound = @klass.find(@obj.id)
|
267
|
+
obj_refound.string_field = "foo"
|
268
|
+
obj_refound.fields_for_partial_update[:set_fields].should == ["string_field"]
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should return a field when it is a new object and it's been initialized with new" do
|
272
|
+
@obj = @klass.new({
|
273
|
+
:string_field => "foo"
|
274
|
+
})
|
275
|
+
@obj.fields_for_partial_update[:set_fields].should =~ ["_id", "string_field"]
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should be able to detect any change in an array (deep copy)" do |variable|
|
279
|
+
@obj = @klass.create!({ :array_field => [["array", "of"], ["arrays"]] })
|
280
|
+
@obj.array_field.last.unshift "many"
|
281
|
+
@obj.save!
|
282
|
+
@obj.reload
|
283
|
+
@obj.array_field.last.should == ["many", "arrays"]
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should be able to detect any change in an array (super deep copy)" do |variable|
|
287
|
+
@obj = @klass.create!({ :array_field => [["array", "of"], ["arrays"]] })
|
288
|
+
@obj.array_field.last << "foo"
|
289
|
+
@obj.fields_for_partial_update[:set_fields].should == ["array_field"]
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should be able to detect a deep change in a hash" do
|
293
|
+
@obj = @klass.new({
|
294
|
+
:hash_field => {
|
295
|
+
:a => {
|
296
|
+
:really => {
|
297
|
+
:deep => :hash
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
})
|
302
|
+
@obj.save!
|
303
|
+
|
304
|
+
@obj.fields_for_partial_update[:set_fields].should == []
|
305
|
+
|
306
|
+
@obj.hash_field[:a][:really] = {
|
307
|
+
:really => {
|
308
|
+
:really => {
|
309
|
+
:really => {
|
310
|
+
:deep => :hash
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
@obj.fields_for_partial_update[:set_fields].should == ["hash_field"]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should set timestamps" do
|
321
|
+
@obj.string_field = "foo"
|
322
|
+
@obj.save!
|
323
|
+
|
324
|
+
@obj.created_at.should_not be_nil
|
325
|
+
@obj.updated_at.should_not be_nil
|
326
|
+
|
327
|
+
@obj.reload
|
328
|
+
@obj.created_at.should_not be_nil
|
329
|
+
@obj.updated_at.should_not be_nil
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should be able to reload set values" do
|
333
|
+
@obj.string_field = "foo"
|
334
|
+
@obj.integer_field = 1
|
335
|
+
@obj.save!
|
336
|
+
|
337
|
+
@obj.reload
|
338
|
+
@obj.string_field.should == "foo"
|
339
|
+
@obj.integer_field.should == 1
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should be able to reload documents created from create" do
|
343
|
+
@obj = @klass.create({
|
344
|
+
:string_field => "foo",
|
345
|
+
:integer_field => 1
|
346
|
+
})
|
347
|
+
|
348
|
+
@obj.reload
|
349
|
+
@obj.string_field.should == "foo"
|
350
|
+
@obj.integer_field.should == 1
|
351
|
+
end
|
352
|
+
|
353
|
+
describe "with embedded documents" do
|
354
|
+
before do
|
355
|
+
@person = @person_class.new
|
356
|
+
@person.pets.build
|
357
|
+
@person.save!
|
358
|
+
@person.reload
|
359
|
+
@pet = @person.pets.first
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should have the child as an update key when the child changes" do
|
363
|
+
@pet.name = "monkey"
|
364
|
+
@person.fields_for_partial_update[:set_fields].should == ["pets"]
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
describe "with a has many" do
|
369
|
+
before do
|
370
|
+
@post_class.partial_updates = true
|
371
|
+
@comments_class.partial_updates = true
|
372
|
+
|
373
|
+
@post_class.many :comments, :class => @comments_class, :foreign_key => :owner_id
|
374
|
+
end
|
375
|
+
|
376
|
+
after do
|
377
|
+
@post_class.destroy_all
|
378
|
+
@comments_class.destroy_all
|
379
|
+
end
|
380
|
+
|
381
|
+
it "should save the children assigned through a hash in new (when assigned through new)" do
|
382
|
+
@post = @post_class.new({
|
383
|
+
:title => "foobar",
|
384
|
+
"comments" => [
|
385
|
+
{ "text" => "one" }
|
386
|
+
],
|
387
|
+
})
|
388
|
+
|
389
|
+
@post.save!
|
390
|
+
@post.reload
|
391
|
+
|
392
|
+
@post.title.should == "foobar"
|
393
|
+
@post.comments.length == 1
|
394
|
+
@post.comments.first.text.should == 'one'
|
395
|
+
end
|
396
|
+
|
397
|
+
it "should save the children assigned through a hash in new (when assigned through new) even when the children are refernced before save" do
|
398
|
+
@post = @post_class.new({
|
399
|
+
:title => "foobar",
|
400
|
+
"comments" => [
|
401
|
+
{ "text" => "one" }
|
402
|
+
],
|
403
|
+
})
|
404
|
+
|
405
|
+
# this line is important - it causes the proxy to load
|
406
|
+
@post.comments.length == 1
|
407
|
+
|
408
|
+
@post.comments.first.should be_persisted
|
409
|
+
@post.comments.first.fields_for_partial_update[:set_fields].should == []
|
410
|
+
|
411
|
+
@post.save!
|
412
|
+
@post.reload
|
413
|
+
|
414
|
+
@post.title.should == "foobar"
|
415
|
+
@post.comments.length.should == 1
|
416
|
+
@post.comments.first.text.should == 'one'
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should update the children after a save if fields have changed" do
|
420
|
+
@post = @post_class.new({
|
421
|
+
:title => "foobar",
|
422
|
+
"comments" => [
|
423
|
+
{ "text" => "one" }
|
424
|
+
],
|
425
|
+
})
|
426
|
+
|
427
|
+
@post.comments.length == 1
|
428
|
+
|
429
|
+
@post.save!
|
430
|
+
@post.reload
|
431
|
+
|
432
|
+
comment = @post.comments.first
|
433
|
+
comment.text = "two"
|
434
|
+
comment.save!
|
435
|
+
comment.reload
|
436
|
+
comment.text.should == "two"
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should save the built document when saving parent" do
|
440
|
+
post = @post_class.create(:title => "foobar")
|
441
|
+
comment = post.comments.build(:text => 'Foo')
|
442
|
+
|
443
|
+
post.save!
|
444
|
+
|
445
|
+
post.should_not be_new
|
446
|
+
comment.should_not be_new
|
447
|
+
end
|
448
|
+
|
449
|
+
it "should clear objects between test runs" do
|
450
|
+
@post_class.count.should == 0
|
451
|
+
@comments_class.count.should == 0
|
452
|
+
end
|
453
|
+
|
454
|
+
it "should only save one object with create" do
|
455
|
+
@post_class.count.should == 0
|
456
|
+
@comments_class.count.should == 0
|
457
|
+
|
458
|
+
@post_class.create(:title => "foobar")
|
459
|
+
@comments_class.create()
|
460
|
+
|
461
|
+
@post_class.count.should == 1
|
462
|
+
@comments_class.count.should == 1
|
463
|
+
end
|
464
|
+
|
465
|
+
it "should save an association with create with the correct attributes" do
|
466
|
+
post = @post_class.create(:title => "foobar")
|
467
|
+
@comments_class.create("text" => 'foo')
|
468
|
+
|
469
|
+
@comments_class.count.should == 1
|
470
|
+
@comments_class.first.text.should == "foo"
|
471
|
+
end
|
472
|
+
|
473
|
+
it "should be able to find objects through the association proxy" do
|
474
|
+
post = @post_class.create!(:title => "foobar")
|
475
|
+
comment = @comments_class.create!("text" => 'foo')
|
476
|
+
|
477
|
+
@comments_class.count.should == 1
|
478
|
+
@comments_class.first.text.should == "foo"
|
479
|
+
|
480
|
+
post.comments << comment
|
481
|
+
|
482
|
+
post.comments.count.should == 1
|
483
|
+
post.comments.first.text.should == "foo"
|
484
|
+
post.comments.all("text" => "foo").length.should == 1
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should work with destroy all and conditions" do
|
488
|
+
@post_class.partial_updates = true
|
489
|
+
@comments_class.partial_updates = true
|
490
|
+
|
491
|
+
post = @post_class.create(:title => "foobar")
|
492
|
+
post.comments << @comments_class.create(:text => '1')
|
493
|
+
post.comments << @comments_class.create(:text => '2')
|
494
|
+
post.comments << @comments_class.create(:text => '3')
|
495
|
+
|
496
|
+
post.comments.count.should == 3
|
497
|
+
post.comments.destroy_all(:text => '1')
|
498
|
+
post.comments.count.should == 2
|
499
|
+
|
500
|
+
post.comments.destroy_all
|
501
|
+
post.comments.count.should == 0
|
502
|
+
end
|
503
|
+
|
504
|
+
it "should work with dealiased keys" do
|
505
|
+
@obj = @dealiased_keys_class.new(:foo => "foo")
|
506
|
+
@obj.save!
|
507
|
+
@obj.reload
|
508
|
+
@obj.foo.should == "foo"
|
509
|
+
|
510
|
+
@obj.foo = "bar"
|
511
|
+
@obj.save!
|
512
|
+
@obj.reload
|
513
|
+
@obj.foo.should == "bar"
|
514
|
+
end
|
515
|
+
|
516
|
+
it "should be able to nullify one associations through re-assignment" do
|
517
|
+
@post = @post_class.create
|
518
|
+
@author = @author_class.new
|
519
|
+
@post.author = @author
|
520
|
+
|
521
|
+
@author.reload
|
522
|
+
@author.authorable_id.should == @post.id
|
523
|
+
|
524
|
+
@post.author = @author_class.new
|
525
|
+
|
526
|
+
@author.reload
|
527
|
+
@author.authorable_id.should be_nil
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|