mark_mapper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|