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,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Documents with the Rails plugin" do
|
4
|
+
let(:doc) { Doc {
|
5
|
+
key :foo, String
|
6
|
+
key :long_field, String, :alias => "lf"
|
7
|
+
}}
|
8
|
+
|
9
|
+
context "with values from the DB" do
|
10
|
+
subject { doc.create(:foo => "bar", :long_field => "long value") }
|
11
|
+
it "should have x_before_type_cast" do
|
12
|
+
subject.foo_before_type_cast.should == "bar"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have x_before_type_cast for aliased fields" do
|
16
|
+
subject.long_field_before_type_cast.should == "long value"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should honor app-set values over DB-set values" do
|
20
|
+
subject.foo = nil
|
21
|
+
subject.foo_before_type_cast.should == nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when blank" do
|
26
|
+
subject { doc.create() }
|
27
|
+
it "should have x_before_type_cast" do
|
28
|
+
subject.foo_before_type_cast.should == nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should honor app-set values over DB-set values" do
|
32
|
+
subject.foo = nil
|
33
|
+
subject.foo_before_type_cast.should == nil
|
34
|
+
|
35
|
+
subject.foo = :baz
|
36
|
+
subject.foo_before_type_cast.should == :baz
|
37
|
+
|
38
|
+
subject.save
|
39
|
+
subject.reload.foo_before_type_cast.should == "baz"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "#has_one" do
|
44
|
+
subject do
|
45
|
+
Doc do
|
46
|
+
has_one :foo
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should create a one association" do
|
51
|
+
subject.associations.should have_key :foo
|
52
|
+
subject.associations[:foo].should be_a MarkMapper::Plugins::Associations::OneAssociation
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,374 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Single collection inheritance (document)" do
|
4
|
+
# context "without a connection", :without_connection => true do
|
5
|
+
# it "should attempt to create a connection during inheritance" do
|
6
|
+
# expect(MarkLogic::Connection).to_not receive(:new)
|
7
|
+
# doc = Class.new
|
8
|
+
# doc.send(:include, MarkMapper::Document)
|
9
|
+
# expect {
|
10
|
+
# Class.new(doc)
|
11
|
+
# }.to_not raise_error
|
12
|
+
# end
|
13
|
+
|
14
|
+
# it "should pick up a connection if one wasn't set" do
|
15
|
+
# doc = Class.new
|
16
|
+
# doc.send(:include, MarkMapper::Document)
|
17
|
+
# klass = Class.new(doc)
|
18
|
+
# klass.connection.should be_nil
|
19
|
+
# MarkMapper.connection
|
20
|
+
# klass.connection.should be_a MarkLogic::Connection
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
|
24
|
+
context "with a connection" do
|
25
|
+
before do
|
26
|
+
class ::DocParent
|
27
|
+
include MarkMapper::Document
|
28
|
+
key :name, String
|
29
|
+
end
|
30
|
+
DocParent.collection.remove
|
31
|
+
|
32
|
+
class ::DocDaughter < ::DocParent; end
|
33
|
+
class ::DocSon < ::DocParent; end
|
34
|
+
class ::DocGrandSon < ::DocSon; end
|
35
|
+
class ::DocGrandGrandSon < ::DocGrandSon; end
|
36
|
+
|
37
|
+
DocSon.many :children, :class_name => 'DocGrandSon'
|
38
|
+
|
39
|
+
@parent = DocParent.new({:name => "Daddy Warbucks"})
|
40
|
+
@daughter = DocDaughter.new({:name => "Little Orphan Annie"})
|
41
|
+
end
|
42
|
+
|
43
|
+
after do
|
44
|
+
Object.send :remove_const, 'DocParent' if defined?(::DocParent)
|
45
|
+
Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
|
46
|
+
Object.send :remove_const, 'DocSon' if defined?(::DocSon)
|
47
|
+
Object.send :remove_const, 'DocGrandSon' if defined?(::DocGrandSon)
|
48
|
+
Object.send :remove_const, 'DocGrandGrandSon' if defined?(::DocGrandGrandSon)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should automatically add _type key to store class" do
|
52
|
+
DocParent.key?(:_type).should be_truthy
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should use the same connection in the subclass" do
|
56
|
+
parent_class = Class.new do
|
57
|
+
include MarkMapper::Document
|
58
|
+
connection MarkLogic::Connection.new(HOST, PORT)
|
59
|
+
end
|
60
|
+
|
61
|
+
child_class = Class.new(parent_class) do
|
62
|
+
include MarkMapper::Document
|
63
|
+
end
|
64
|
+
|
65
|
+
child_class.connection.should == child_class.connection
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should use the same database in the subclass" do
|
69
|
+
parent_class = Class.new do
|
70
|
+
include MarkMapper::Document
|
71
|
+
database = MarkMapper.application.content_databases[0]
|
72
|
+
end
|
73
|
+
|
74
|
+
child_class = Class.new(parent_class) do
|
75
|
+
include MarkMapper::Document
|
76
|
+
end
|
77
|
+
|
78
|
+
child_class.database.should == MarkMapper.application.content_databases[0]
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should use the same collection in the subclass" do
|
82
|
+
DocDaughter.collection.name.should == DocParent.collection.name
|
83
|
+
end
|
84
|
+
|
85
|
+
context "if the subclass changes its collection" do
|
86
|
+
before do
|
87
|
+
class ::DocSCIOrphan < ::DocParent
|
88
|
+
set_collection_name "foobars"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
after do
|
93
|
+
Object.send :remove_const, 'DocSCIOrphan' if defined?(::DocSCIOrphan)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should negate SCI" do
|
97
|
+
DocSCIOrphan.collection.name.should == "foobars"
|
98
|
+
DocSCIOrphan.should_not be_single_collection_inherited
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should remove the _type key" do
|
102
|
+
DocParent.keys.should_not have_key "_type"
|
103
|
+
DocSCIOrphan.keys.should_not have_key "_type"
|
104
|
+
end
|
105
|
+
|
106
|
+
context "and then is subclassed again" do
|
107
|
+
before do
|
108
|
+
class ::DocSCIOrphanChild < ::DocSCIOrphan
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
after do
|
113
|
+
Object.send :remove_const, 'DocSCIOrphanChild' if defined?(::DocSCIOrphanChild)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should reinstate SCI" do
|
117
|
+
DocSCIOrphan.should_not be_single_collection_inherited
|
118
|
+
DocSCIOrphanChild.should be_single_collection_inherited
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should have the _type key" do
|
122
|
+
DocSCIOrphan.keys.should have_key "_type"
|
123
|
+
DocSCIOrphanChild.keys.should have_key "_type"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should know single_collection_parent" do
|
129
|
+
DocParent.single_collection_parent.should be_nil
|
130
|
+
DocDaughter.single_collection_parent.should == DocParent
|
131
|
+
DocSon.single_collection_parent.should == DocParent
|
132
|
+
DocGrandSon.single_collection_parent.should == DocSon
|
133
|
+
DocGrandGrandSon.single_collection_parent.should == DocGrandSon
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should know single_collection_root" do
|
137
|
+
DocParent.single_collection_root.should == DocParent
|
138
|
+
DocDaughter.single_collection_root.should == DocParent
|
139
|
+
DocSon.single_collection_root.should == DocParent
|
140
|
+
DocGrandSon.single_collection_root.should == DocParent
|
141
|
+
DocGrandGrandSon.single_collection_root.should == DocParent
|
142
|
+
end
|
143
|
+
|
144
|
+
context ".single_collection_inherited?" do
|
145
|
+
it "should be false if has not inherited" do
|
146
|
+
DocParent.should_not be_single_collection_inherited
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should be true if inherited" do
|
150
|
+
DocDaughter.should be_single_collection_inherited
|
151
|
+
DocSon.should be_single_collection_inherited
|
152
|
+
DocGrandSon.should be_single_collection_inherited
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should set _type on initialize" do
|
157
|
+
DocDaughter.new._type.should == 'DocDaughter'
|
158
|
+
DocSon.new._type.should == 'DocSon'
|
159
|
+
DocGrandSon.new._type.should == 'DocGrandSon'
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should set _type based on class and ignore assigned values" do
|
163
|
+
DocSon.new(:_type => 'DocDaughter')._type.should == 'DocSon'
|
164
|
+
end
|
165
|
+
|
166
|
+
context "loading" do
|
167
|
+
it "should be based on _type" do
|
168
|
+
@parent.save
|
169
|
+
@daughter.save
|
170
|
+
|
171
|
+
collection = DocParent.all
|
172
|
+
collection.size.should == 2
|
173
|
+
collection.first.should be_kind_of(DocParent)
|
174
|
+
collection.first.name.should == "Daddy Warbucks"
|
175
|
+
collection.last.should be_kind_of(DocDaughter)
|
176
|
+
collection.last.name.should == "Little Orphan Annie"
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should gracefully handle when _type cannot be constantized" do
|
180
|
+
doc = DocParent.new(:name => 'Nunes')
|
181
|
+
doc._type = 'FoobarBaz'
|
182
|
+
doc.save
|
183
|
+
|
184
|
+
collection = DocParent.all
|
185
|
+
collection.last.should == doc
|
186
|
+
collection.last.should be_kind_of(DocParent)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context "querying" do
|
191
|
+
it "should find scoped to class" do
|
192
|
+
john = DocSon.create(:name => 'John')
|
193
|
+
steve = DocSon.create(:name => 'Steve')
|
194
|
+
steph = DocDaughter.create(:name => 'Steph')
|
195
|
+
carrie = DocDaughter.create(:name => 'Carrie')
|
196
|
+
boris = DocGrandSon.create(:name => 'Boris')
|
197
|
+
|
198
|
+
DocGrandGrandSon.all(:order => 'name').should == []
|
199
|
+
DocGrandSon.all(:order => 'name').should == [boris]
|
200
|
+
DocSon.all(:order => 'name').should == [boris, john, steve]
|
201
|
+
DocDaughter.all(:order => 'name').should == [carrie, steph]
|
202
|
+
DocParent.all(:order => 'name').should == [boris, carrie, john, steph, steve]
|
203
|
+
|
204
|
+
sigmund = DocGrandGrandSon.create(:name => 'Sigmund')
|
205
|
+
|
206
|
+
DocGrandSon.all(:order => 'name').should == [boris, sigmund]
|
207
|
+
DocSon.all(:order => 'name').should == [boris, john, sigmund, steve]
|
208
|
+
DocParent.all(:order => 'name').should == [boris, carrie, john, sigmund, steph, steve]
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should work with nested hash conditions" do
|
212
|
+
john = DocSon.create(:name => 'John')
|
213
|
+
steve = DocSon.create(:name => 'Steve')
|
214
|
+
DocSon.all(:name => {'$ne' => 'Steve'}).should == [john]
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should raise error if not found scoped to class" do
|
218
|
+
john = DocSon.create(:name => 'John')
|
219
|
+
steph = DocDaughter.create(:name => 'Steph')
|
220
|
+
|
221
|
+
lambda {
|
222
|
+
DocSon.find!(steph._id)
|
223
|
+
}.should raise_error(MarkMapper::DocumentNotFound)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should not raise error for find with parent" do
|
227
|
+
john = DocSon.create(:name => 'John')
|
228
|
+
|
229
|
+
DocParent.find!(john._id).should == john
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should count scoped to class" do
|
233
|
+
john = DocSon.create(:name => 'John')
|
234
|
+
steve = DocSon.create(:name => 'Steve')
|
235
|
+
steph = DocDaughter.create(:name => 'Steph')
|
236
|
+
carrie = DocDaughter.create(:name => 'Carrie')
|
237
|
+
|
238
|
+
DocGrandSon.count.should == 0
|
239
|
+
DocSon.count.should == 2
|
240
|
+
DocDaughter.count.should == 2
|
241
|
+
DocParent.count.should == 4
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should not be able to destroy each other" do
|
245
|
+
john = DocSon.create(:name => 'John')
|
246
|
+
steph = DocDaughter.create(:name => 'Steph')
|
247
|
+
|
248
|
+
lambda {
|
249
|
+
DocSon.destroy(steph._id)
|
250
|
+
}.should raise_error(MarkMapper::DocumentNotFound)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should not be able to delete each other" do
|
254
|
+
john = DocSon.create(:name => 'John')
|
255
|
+
steph = DocDaughter.create(:name => 'Steph')
|
256
|
+
|
257
|
+
lambda {
|
258
|
+
DocSon.delete(steph._id)
|
259
|
+
}.should_not change { DocParent.count }
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should be able to destroy using parent" do
|
263
|
+
john = DocSon.create(:name => 'John')
|
264
|
+
steph = DocDaughter.create(:name => 'Steph')
|
265
|
+
|
266
|
+
lambda {
|
267
|
+
DocParent.destroy_all
|
268
|
+
}.should change { DocParent.count }.by(-2)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should be able to delete using parent" do
|
272
|
+
john = DocSon.create(:name => 'John')
|
273
|
+
steph = DocDaughter.create(:name => 'Steph')
|
274
|
+
|
275
|
+
lambda {
|
276
|
+
DocParent.delete_all
|
277
|
+
}.should change { DocParent.count }.by(-2)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should be able to reload single collection inherited parent class" do
|
282
|
+
brian = DocParent.create(:name => 'Brian')
|
283
|
+
brian.name = 'B-Dawg'
|
284
|
+
brian.reload
|
285
|
+
brian.name.should == 'Brian'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe "Single collection inheritance (embedded document)" do
|
290
|
+
before do
|
291
|
+
class ::Grandparent
|
292
|
+
include MarkMapper::EmbeddedDocument
|
293
|
+
key :grandparent, String
|
294
|
+
end
|
295
|
+
|
296
|
+
class ::Parent < ::Grandparent
|
297
|
+
include MarkMapper::EmbeddedDocument
|
298
|
+
key :parent, String
|
299
|
+
end
|
300
|
+
|
301
|
+
class ::Child < ::Parent
|
302
|
+
include MarkMapper::EmbeddedDocument
|
303
|
+
key :child, String
|
304
|
+
end
|
305
|
+
|
306
|
+
class ::OtherChild < ::Parent
|
307
|
+
include MarkMapper::EmbeddedDocument
|
308
|
+
key :other_child, String
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
after do
|
313
|
+
Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
|
314
|
+
Object.send :remove_const, 'Parent' if defined?(::Parent)
|
315
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
316
|
+
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should automatically add _type key" do
|
320
|
+
Grandparent.key?(:_type).should be_truthy
|
321
|
+
end
|
322
|
+
|
323
|
+
context ".single_collection_inherited?" do
|
324
|
+
it "should be false if has not inherited" do
|
325
|
+
Grandparent.should_not be_single_collection_inherited
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should be true if inherited" do
|
329
|
+
Parent.should be_single_collection_inherited
|
330
|
+
Child.should be_single_collection_inherited
|
331
|
+
OtherChild.should be_single_collection_inherited
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should set _type on initialize" do
|
336
|
+
Parent.new._type.should == 'Parent'
|
337
|
+
Child.new._type.should == 'Child'
|
338
|
+
OtherChild.new._type.should == 'OtherChild'
|
339
|
+
end
|
340
|
+
|
341
|
+
it "should set _type based on class and ignore assigned values" do
|
342
|
+
Child.new(:_type => 'OtherChild')._type.should == 'Child'
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
describe "With polymorphism" do
|
347
|
+
before :all do
|
348
|
+
class SciPolymorphicPost
|
349
|
+
include MarkMapper::Document
|
350
|
+
belongs_to :article_parent, :polymorphic => true
|
351
|
+
end
|
352
|
+
|
353
|
+
class GalleryItem
|
354
|
+
include MarkMapper::Document
|
355
|
+
belongs_to :gallery_album
|
356
|
+
key :text, Hash
|
357
|
+
timestamps!
|
358
|
+
end
|
359
|
+
|
360
|
+
class TextGalleryItem < GalleryItem;
|
361
|
+
many :sci_polymorphic_posts, :as => :article_parent
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should find polymorphic SCI items" do
|
366
|
+
item = TextGalleryItem.new()
|
367
|
+
p = SciPolymorphicPost.create(:article_parent => item)
|
368
|
+
p.article_parent_id.should be_a MarkLogic::ObjectId
|
369
|
+
p.article_parent_type.should == "TextGalleryItem"
|
370
|
+
|
371
|
+
p.reload.article_parent.sci_polymorphic_posts.all.should include(p)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Scopes" do
|
4
|
+
context "Scopes" do
|
5
|
+
before do
|
6
|
+
@document = Doc() do
|
7
|
+
key :name, String
|
8
|
+
key :age, Integer
|
9
|
+
timestamps!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "basic scopes" do
|
14
|
+
before do
|
15
|
+
@document.class_eval do
|
16
|
+
scope :old, :age.gt => 60
|
17
|
+
scope :teens, :age.ge => 13, :age.le => 19
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should know what scopes have been added" do
|
22
|
+
@document.scopes.size.should == 2
|
23
|
+
@document.scopes.keys.map(&:to_s).sort.should == %w(old teens)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return a query" do
|
27
|
+
@document.old.should be_kind_of(MarkMapper::Query)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should work" do
|
31
|
+
@document.create(:name => 'John', :age => 99)
|
32
|
+
@document.create(:name => 'Frank', :age => 15)
|
33
|
+
docs = @document.old.all
|
34
|
+
docs.size.should == 1
|
35
|
+
docs[0].name.should == 'John'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Regression test for #534
|
39
|
+
context "when where() is invoked via a scope before a key is defined" do
|
40
|
+
let(:given_id) { MarkLogic::ObjectId.new }
|
41
|
+
let(:doc) { Doc {
|
42
|
+
key :type, String
|
43
|
+
|
44
|
+
# Ordering is important here; where needs to happen before foo_id is defined
|
45
|
+
# in order to produce the behavior we're testing against regression.
|
46
|
+
scope :type, where(:type => "bar")
|
47
|
+
key :foo_id, ObjectId
|
48
|
+
}}
|
49
|
+
before {
|
50
|
+
doc.collection.drop
|
51
|
+
doc.create({:foo_id => given_id})
|
52
|
+
}
|
53
|
+
|
54
|
+
it "should work without typecasts" do
|
55
|
+
doc.where(:foo_id => given_id).count.should == 1
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should work with typecasts" do
|
59
|
+
doc.where(:foo_id => given_id.to_s).count.should == 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "dynamic scopes" do
|
65
|
+
before do
|
66
|
+
@document.class_eval do
|
67
|
+
scope :age, lambda { |age| {:age => age} }
|
68
|
+
scope :ages, lambda { |low, high| {:age.ge => low, :age.le => high} }
|
69
|
+
scope :ordered, lambda { |sort| sort(sort) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should work with single argument" do
|
74
|
+
@document.create(:name => 'John', :age => 60)
|
75
|
+
@document.create(:name => 'Frank', :age => 50)
|
76
|
+
docs = @document.age(60).all
|
77
|
+
docs.size.should == 1
|
78
|
+
docs.first.name.should == 'John'
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should work with multiple arguments" do
|
82
|
+
@document.create(:name => 'John', :age => 60)
|
83
|
+
@document.create(:name => 'Frank', :age => 50)
|
84
|
+
@document.create(:name => 'Bill', :age => 40)
|
85
|
+
docs = @document.ages(50, 70).all
|
86
|
+
docs.size.should == 2
|
87
|
+
docs.map(&:name).sort.should == %w(Frank John)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should work with queries" do
|
91
|
+
john = @document.create(:name => 'John', :age => 60)
|
92
|
+
frank = @document.create(:name => 'Frank', :age => 50)
|
93
|
+
bill = @document.create(:name => 'Bill', :age => 40)
|
94
|
+
@document.ordered(:age).all.should == [bill, frank, john]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "query scopes" do
|
99
|
+
before do
|
100
|
+
@document.class_eval do
|
101
|
+
scope :boomers, where(:age.ge => 60).sort(:age)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should work" do
|
106
|
+
todd = @document.create(:name => 'Todd', :age => 65)
|
107
|
+
john = @document.create(:name => 'John', :age => 60)
|
108
|
+
@document.create(:name => 'Frank', :age => 50)
|
109
|
+
@document.create(:name => 'Bill', :age => 40)
|
110
|
+
docs = @document.boomers.all
|
111
|
+
docs[0].should == john
|
112
|
+
docs[1].should == todd
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "chaining" do
|
117
|
+
before do
|
118
|
+
@document.class_eval do
|
119
|
+
scope :by_age, lambda { |age| {:age => age} }
|
120
|
+
scope :by_name, lambda { |name| {:name => name} }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should work with scope methods" do
|
125
|
+
@document.create(:name => 'John', :age => 60)
|
126
|
+
@document.create(:name => 'Frank', :age => 60)
|
127
|
+
@document.create(:name => 'Bill', :age => 50)
|
128
|
+
docs = @document.by_age(60).by_name('John').all
|
129
|
+
docs.size.should == 1
|
130
|
+
docs.first.name.should == 'John'
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should work on query methods" do
|
134
|
+
@document.create(:name => 'John', :age => 60)
|
135
|
+
@document.create(:name => 'John', :age => 50)
|
136
|
+
@document.create(:name => 'Bill', :age => 50)
|
137
|
+
docs = @document.where(:name => 'John').by_age(50).all
|
138
|
+
docs.size.should == 1
|
139
|
+
docs.first.age.should == 50
|
140
|
+
end
|
141
|
+
|
142
|
+
context "with model methods" do
|
143
|
+
it "should work if method returns a query" do
|
144
|
+
@document.create(:name => 'John', :age => 10)
|
145
|
+
@document.create(:name => 'John', :age => 20)
|
146
|
+
@document.class_eval do
|
147
|
+
def self.young
|
148
|
+
query(:age.le => 12)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
docs = @document.by_name('John').young.all
|
152
|
+
docs.size.should == 1
|
153
|
+
docs.first.age.should == 10
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should not work if method does not return a query" do
|
157
|
+
@document.class_eval { def self.age; 20 end }
|
158
|
+
@document.by_name('John').age.should == 20
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "with single collection inheritance" do
|
164
|
+
before do
|
165
|
+
class ::Item
|
166
|
+
include MarkMapper::Document
|
167
|
+
scope :by_title, lambda { |title| {:title => title} }
|
168
|
+
scope :published, lambda { {:published_at.le => Time.now.utc} }
|
169
|
+
|
170
|
+
key :title, String
|
171
|
+
key :published_at, Time
|
172
|
+
end
|
173
|
+
Item.collection.remove
|
174
|
+
|
175
|
+
class ::Page < ::Item; end
|
176
|
+
class ::Blog < ::Item
|
177
|
+
key :slug, String
|
178
|
+
scope :by_slug, lambda { |slug| {:slug => slug} }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
after do
|
183
|
+
Object.send :remove_const, 'Item' if defined?(::Item)
|
184
|
+
Object.send :remove_const, 'Page' if defined?(::Page)
|
185
|
+
Object.send :remove_const, 'Blog' if defined?(::Blog)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should inherit scopes" do
|
189
|
+
Page.scopes.keys.map(&:to_s).sort.should == %w(by_title published)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should work with _type" do
|
193
|
+
item = Item.create(:title => 'Home')
|
194
|
+
page = Page.create(:title => 'Home')
|
195
|
+
Page.by_title('Home').first.should == page
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should limit subclass scopes to subclasses" do
|
199
|
+
Item.scopes.keys.map(&:to_s).should =~ %w(by_title published)
|
200
|
+
Blog.scopes.keys.map(&:to_s).should =~ %w(by_slug by_title published)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|