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,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "DynamicFinder" do
|
4
|
+
DynamicFinder = MarkMapper::Plugins::DynamicQuerying::DynamicFinder
|
5
|
+
|
6
|
+
it "should initialize with method" do
|
7
|
+
finder = DynamicFinder.new(:foobar)
|
8
|
+
finder.method.should == :foobar
|
9
|
+
end
|
10
|
+
|
11
|
+
context "found?" do
|
12
|
+
it "should be true for find_by" do
|
13
|
+
DynamicFinder.new(:find_by_foo).found?.should be_truthy
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be true for find_by with !" do
|
17
|
+
DynamicFinder.new(:find_by_foo!).found?.should be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be true for find_all_by" do
|
21
|
+
DynamicFinder.new(:find_all_by_foo).found?.should be_truthy
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be true for find_or_initialize_by" do
|
25
|
+
DynamicFinder.new(:find_or_initialize_by_foo).found?.should be_truthy
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be true for find_or_create_by" do
|
29
|
+
DynamicFinder.new(:find_or_create_by_foo).found?.should be_truthy
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be false for anything else" do
|
33
|
+
[:foobar, :bazwick].each do |method|
|
34
|
+
DynamicFinder.new(method).found?.should be_falsey
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "find_all_by" do
|
40
|
+
it "should parse one attribute" do
|
41
|
+
DynamicFinder.new(:find_all_by_foo).attributes.should == %w(foo)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should parse multiple attributes" do
|
45
|
+
DynamicFinder.new(:find_all_by_foo_and_bar).attributes.should == %w(foo bar)
|
46
|
+
DynamicFinder.new(:find_all_by_foo_and_bar_and_baz).attributes.should == %w(foo bar baz)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should set finder to :all" do
|
50
|
+
DynamicFinder.new(:find_all_by_foo_and_bar).finder.should == :all
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "find_by" do
|
55
|
+
it "should parse one attribute" do
|
56
|
+
DynamicFinder.new(:find_by_foo).attributes.should == %w(foo)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should parse multiple attributes" do
|
60
|
+
DynamicFinder.new(:find_by_foo_and_bar).attributes.should == %w(foo bar)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should set finder to :first" do
|
64
|
+
DynamicFinder.new(:find_by_foo).finder.should == :first
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should set bang to false" do
|
68
|
+
DynamicFinder.new(:find_by_foo).bang.should be_falsey
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "find_by with !" do
|
73
|
+
it "should parse one attribute" do
|
74
|
+
DynamicFinder.new(:find_by_foo!).attributes.should == %w(foo)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should parse multiple attributes" do
|
78
|
+
DynamicFinder.new(:find_by_foo_and_bar!).attributes.should == %w(foo bar)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should set finder to :first" do
|
82
|
+
DynamicFinder.new(:find_by_foo!).finder.should == :first
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should set bang to true" do
|
86
|
+
DynamicFinder.new(:find_by_foo!).bang.should be_truthy
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "find_or_initialize_by" do
|
91
|
+
it "should parse one attribute" do
|
92
|
+
DynamicFinder.new(:find_or_initialize_by_foo).attributes.should == %w(foo)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should parse multiple attributes" do
|
96
|
+
DynamicFinder.new(:find_or_initialize_by_foo_and_bar).attributes.should == %w(foo bar)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should set finder to :first" do
|
100
|
+
DynamicFinder.new(:find_or_initialize_by_foo).finder.should == :first
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should set instantiator to new" do
|
104
|
+
DynamicFinder.new(:find_or_initialize_by_foo).instantiator.should == :new
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "find_or_create_by" do
|
109
|
+
it "should parse one attribute" do
|
110
|
+
DynamicFinder.new(:find_or_create_by_foo).attributes.should == %w(foo)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should parse multiple attributes" do
|
114
|
+
DynamicFinder.new(:find_or_create_by_foo_and_bar).attributes.should == %w(foo bar)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should set finder to :first" do
|
118
|
+
DynamicFinder.new(:find_or_create_by_foo).finder.should == :first
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should set instantiator to new" do
|
122
|
+
DynamicFinder.new(:find_or_create_by_foo).instantiator.should == :create
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,676 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module KeyOverride
|
4
|
+
def other_child
|
5
|
+
self[:other_child] || "special result"
|
6
|
+
end
|
7
|
+
|
8
|
+
def other_child=(value)
|
9
|
+
super(value + " modified")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "EmbeddedDocument" do
|
14
|
+
context "EmbeddedDocuments" do
|
15
|
+
before do
|
16
|
+
class ::Grandparent
|
17
|
+
include MarkMapper::EmbeddedDocument
|
18
|
+
key :grandparent, String
|
19
|
+
end
|
20
|
+
|
21
|
+
class ::Parent < ::Grandparent
|
22
|
+
include MarkMapper::EmbeddedDocument
|
23
|
+
key :parent, String
|
24
|
+
end
|
25
|
+
|
26
|
+
class ::Child < ::Parent
|
27
|
+
include MarkMapper::EmbeddedDocument
|
28
|
+
key :child, String
|
29
|
+
end
|
30
|
+
|
31
|
+
class ::OtherChild < ::Parent
|
32
|
+
include MarkMapper::EmbeddedDocument
|
33
|
+
include KeyOverride
|
34
|
+
|
35
|
+
key :other_child, String
|
36
|
+
end
|
37
|
+
|
38
|
+
class ::EDocWithAValidation
|
39
|
+
include MarkMapper::EmbeddedDocument
|
40
|
+
key :name, String, :required => true
|
41
|
+
end
|
42
|
+
|
43
|
+
class ::DocWithAValidation
|
44
|
+
include MarkMapper::Document
|
45
|
+
key :name, String, :required => true
|
46
|
+
many :e_doc_with_a_validations
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
after do
|
51
|
+
Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
|
52
|
+
Object.send :remove_const, 'Parent' if defined?(::Parent)
|
53
|
+
Object.send :remove_const, 'Child' if defined?(::Child)
|
54
|
+
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
|
55
|
+
Object.send :remove_const, 'EDocWithAValidation' if defined?(::EDocWithAValidation)
|
56
|
+
Object.send :remove_const, 'DocWithAValidation' if defined?(::DocWithAValidation)
|
57
|
+
end
|
58
|
+
|
59
|
+
context "Including MarkMapper::EmbeddedDocument in a class" do
|
60
|
+
before do
|
61
|
+
@klass = EDoc()
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should add _id key" do
|
65
|
+
@klass.keys['_id'].should_not be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should know it is using object id" do
|
69
|
+
@klass.using_object_id?.should be_truthy
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should know it is not using object id if _id type is changed" do
|
73
|
+
@klass.key :_id, String
|
74
|
+
@klass.using_object_id?.should be_falsey
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "Class Methods" do
|
79
|
+
it "should include logger" do
|
80
|
+
@klass = EDoc()
|
81
|
+
@klass.logger.should == MarkMapper.logger
|
82
|
+
@klass.logger.should be_instance_of(Logger)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return false for embeddable" do
|
86
|
+
EDoc().embeddable?.should be_truthy
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#to_marklogic" do
|
90
|
+
before { @klass = EDoc() }
|
91
|
+
|
92
|
+
it "should be nil if nil" do
|
93
|
+
@klass.to_marklogic(nil).should be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should convert to_marklogic for other values" do
|
97
|
+
doc = @klass.new(:foo => 'bar')
|
98
|
+
to_marklogic = @klass.to_marklogic(doc)
|
99
|
+
to_marklogic.is_a?(Hash).should be_truthy
|
100
|
+
to_marklogic['foo'].should == 'bar'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "#from_marklogic" do
|
105
|
+
before { @klass = EDoc() }
|
106
|
+
|
107
|
+
it "should be nil if nil" do
|
108
|
+
@klass.from_marklogic(nil).should be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be instance if instance of class" do
|
112
|
+
doc = @klass.new
|
113
|
+
@klass.from_marklogic(doc).should == doc
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be instance if hash of attributes" do
|
117
|
+
doc = @klass.from_marklogic({:foo => 'bar'})
|
118
|
+
doc.instance_of?(@klass).should be_truthy
|
119
|
+
doc.foo.should == 'bar'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "defining a key" do
|
124
|
+
before do
|
125
|
+
@document = EDoc()
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should work with name" do
|
129
|
+
key = @document.key(:name)
|
130
|
+
key.name.should == 'name'
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should work with name and type" do
|
134
|
+
key = @document.key(:name, String)
|
135
|
+
key.name.should == 'name'
|
136
|
+
key.type.should == String
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should work with name, type and options" do
|
140
|
+
key = @document.key(:name, String, :required => true)
|
141
|
+
key.name.should == 'name'
|
142
|
+
key.type.should == String
|
143
|
+
key.options[:required].should be_truthy
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should work with name and options" do
|
147
|
+
key = @document.key(:name, :required => true)
|
148
|
+
key.name.should == 'name'
|
149
|
+
key.options[:required].should be_truthy
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should be tracked per document" do
|
153
|
+
@document.key(:name, String)
|
154
|
+
@document.key(:age, Integer)
|
155
|
+
@document.keys['name'].name.should == 'name'
|
156
|
+
@document.keys['name'].type.should == String
|
157
|
+
@document.keys['age'].name.should == 'age'
|
158
|
+
@document.keys['age'].type.should == Integer
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should be redefinable" do
|
162
|
+
@document.key(:foo, String)
|
163
|
+
@document.keys['foo'].type.should == String
|
164
|
+
@document.key(:foo, Integer)
|
165
|
+
@document.keys['foo'].type.should == Integer
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should create reader method" do
|
169
|
+
@document.new.should_not respond_to(:foo)
|
170
|
+
@document.key(:foo, String)
|
171
|
+
@document.new.should respond_to(:foo)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should create reader before type cast method" do
|
175
|
+
@document.new.should_not respond_to(:foo_before_type_cast)
|
176
|
+
@document.key(:foo, String)
|
177
|
+
@document.new.should respond_to(:foo_before_type_cast)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should create writer method" do
|
181
|
+
@document.new.should_not respond_to(:foo=)
|
182
|
+
@document.key(:foo, String)
|
183
|
+
@document.new.should respond_to(:foo=)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should create boolean method" do
|
187
|
+
@document.new.should_not respond_to(:foo?)
|
188
|
+
@document.key(:foo, String)
|
189
|
+
@document.new.should respond_to(:foo?)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "keys" do
|
194
|
+
it "should be inherited" do
|
195
|
+
Grandparent.keys.keys.sort.should == ['_id', '_type', 'grandparent']
|
196
|
+
Parent.keys.keys.sort.should == ['_id', '_type', 'grandparent', 'parent']
|
197
|
+
Child.keys.keys.sort.should == ['_id', '_type', 'child', 'grandparent', 'parent']
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should propogate to descendants if key added after class definition" do
|
201
|
+
Grandparent.key :foo, String
|
202
|
+
|
203
|
+
Grandparent.keys.keys.sort.should == ['_id', '_type', 'foo', 'grandparent']
|
204
|
+
Parent.keys.keys.sort.should == ['_id', '_type', 'foo', 'grandparent', 'parent']
|
205
|
+
Child.keys.keys.sort.should == ['_id', '_type', 'child', 'foo', 'grandparent', 'parent']
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should not add anonymous objects to the ancestor tree" do
|
209
|
+
OtherChild.ancestors.any? { |a| a.name.blank? }.should be_falsey
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should not include descendant keys" do
|
213
|
+
lambda { Parent.new.other_child }.should raise_error
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "descendants" do
|
218
|
+
it "should default to an empty array" do
|
219
|
+
Child.descendants.should == []
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should be recorded" do
|
223
|
+
Grandparent.direct_descendants.should == [Parent]
|
224
|
+
Grandparent.descendants.to_set.should == [Parent, Child, OtherChild].to_set
|
225
|
+
|
226
|
+
Parent.descendants.should == [Child, OtherChild]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "An instance of an embedded document" do
|
232
|
+
before do
|
233
|
+
@document = EDoc do
|
234
|
+
key :name, String
|
235
|
+
key :age, Integer
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should respond to cache_key" do
|
240
|
+
@document.new.should respond_to(:cache_key)
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should have access to class logger" do
|
244
|
+
doc = @document.new
|
245
|
+
doc.logger.should == @document.logger
|
246
|
+
doc.logger.should be_instance_of(Logger)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should automatically have an _id key" do
|
250
|
+
@document.keys.keys.should include('_id')
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should create id during initialization" do
|
254
|
+
@document.new._id.should be_instance_of(MarkLogic::ObjectId)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should have id method returns _id" do
|
258
|
+
id = MarkLogic::ObjectId.new
|
259
|
+
doc = @document.new(:_id => id)
|
260
|
+
doc.id.should == id
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should convert string object id to marklogic object id when assigning id with _id object id type" do
|
264
|
+
id = MarkLogic::ObjectId.new
|
265
|
+
doc = @document.new(:id => id.to_s)
|
266
|
+
doc._id.should == id
|
267
|
+
doc.id.should == id
|
268
|
+
doc = @document.new(:_id => id.to_s)
|
269
|
+
doc._id.should == id
|
270
|
+
doc.id.should == id
|
271
|
+
end
|
272
|
+
|
273
|
+
context "_parent_document" do
|
274
|
+
it "should default to nil" do
|
275
|
+
@document.new._parent_document.should be_nil
|
276
|
+
@document.new._root_document.should be_nil
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should set _root_document when setting _parent_document" do
|
280
|
+
root = Doc().new
|
281
|
+
doc = @document.new(:_parent_document => root)
|
282
|
+
doc._parent_document.should be(root)
|
283
|
+
doc._root_document.should be(root)
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should set _root_document when setting _parent_document on embedded many" do
|
287
|
+
root = Doc().new
|
288
|
+
klass = EDoc { many :children }
|
289
|
+
parent = klass.new(:_parent_document => root, :children => [{}])
|
290
|
+
child = parent.children.first
|
291
|
+
child._parent_document.should be(parent)
|
292
|
+
child._root_document.should be(root)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "being initialized" do
|
297
|
+
it "should accept a hash that sets keys and values" do
|
298
|
+
doc = @document.new(:name => 'John', :age => 23)
|
299
|
+
doc.attributes.keys.sort.should == ['_id', 'age', 'name']
|
300
|
+
doc.attributes['name'].should == 'John'
|
301
|
+
doc.attributes['age'].should == 23
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should be able to assign keys dynamically" do
|
305
|
+
doc = @document.new(:name => 'John', :skills => ['ruby', 'rails'])
|
306
|
+
doc.name.should == 'John'
|
307
|
+
doc.skills.should == ['ruby', 'rails']
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should not throw error if initialized with nil" do
|
311
|
+
expect { @document.new(nil) }.to_not raise_error
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "initialized when _type key present" do
|
316
|
+
before do
|
317
|
+
@klass = EDoc('FooBar') { key :_type, String }
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should set _type to class name" do
|
321
|
+
@klass.new._type.should == 'FooBar'
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should ignore _type attribute and always use class" do
|
325
|
+
@klass.new(:_type => 'Foo')._type.should == 'FooBar'
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
context "attributes=" do
|
330
|
+
it "should update values for keys provided" do
|
331
|
+
doc = @document.new(:name => 'foobar', :age => 10)
|
332
|
+
doc.attributes = {:name => 'new value', :age => 5}
|
333
|
+
doc.attributes[:name].should == 'new value'
|
334
|
+
doc.attributes[:age].should == 5
|
335
|
+
end
|
336
|
+
|
337
|
+
it "should not update values for keys that were not provided" do
|
338
|
+
doc = @document.new(:name => 'foobar', :age => 10)
|
339
|
+
doc.attributes = {:name => 'new value'}
|
340
|
+
doc.attributes[:name].should == 'new value'
|
341
|
+
doc.attributes[:age].should == 10
|
342
|
+
end
|
343
|
+
|
344
|
+
it "should work with pre-defined methods" do
|
345
|
+
@document.class_eval do
|
346
|
+
attr_writer :password
|
347
|
+
|
348
|
+
def passwd
|
349
|
+
@password
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
doc = @document.new(:name => 'foobar', :password => 'secret')
|
354
|
+
doc.passwd.should == 'secret'
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should type cast key values" do
|
358
|
+
doc = @document.new(:name => 1234, :age => '21')
|
359
|
+
doc.name.should == '1234'
|
360
|
+
doc.age.should == 21
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context "attributes" do
|
365
|
+
it "should default to hash with all keys" do
|
366
|
+
doc = @document.new
|
367
|
+
doc.keys.keys.sort.should == ['_id', 'age', 'name']
|
368
|
+
doc.attributes.keys.sort.should == ['_id']
|
369
|
+
end
|
370
|
+
|
371
|
+
it "should return all keys with values" do
|
372
|
+
doc = @document.new(:name => 'string', :age => nil)
|
373
|
+
doc.attributes.keys.sort.should == ['_id', 'name']
|
374
|
+
doc.keys.keys.sort.should == ['_id', 'age', 'name']
|
375
|
+
doc.attributes.values.should include('string')
|
376
|
+
doc.attributes.values.should_not include(nil)
|
377
|
+
end
|
378
|
+
|
379
|
+
it "should have indifferent access" do
|
380
|
+
doc = @document.new(:name => 'string')
|
381
|
+
doc.attributes[:name].should == 'string'
|
382
|
+
doc.attributes['name'].should == 'string'
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
context "to_marklogic" do
|
387
|
+
it "should default to hash with _id key" do
|
388
|
+
doc = @document.new
|
389
|
+
doc.to_marklogic.keys.sort.should == ['_id']
|
390
|
+
doc.keys.keys.sort.should == ['_id', 'age', 'name']
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should return all keys" do
|
394
|
+
doc = @document.new(:name => 'string', :age => nil)
|
395
|
+
doc.keys.keys.sort.should == ['_id', 'age', 'name']
|
396
|
+
doc.to_marklogic.keys.sort.should == ['_id','name']
|
397
|
+
doc.to_marklogic.values.should include('string')
|
398
|
+
doc.to_marklogic.values.should_not include(nil)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context "key shorcut access" do
|
403
|
+
context "[]" do
|
404
|
+
it "should work when key found" do
|
405
|
+
doc = @document.new(:name => 'string')
|
406
|
+
doc[:name].should == 'string'
|
407
|
+
end
|
408
|
+
|
409
|
+
it "should return nil when not found" do
|
410
|
+
doc = @document.new(:name => 'string')
|
411
|
+
doc[:not_here].should be_nil
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
context "[]=" do
|
416
|
+
it "should write key value for existing key" do
|
417
|
+
doc = @document.new
|
418
|
+
doc[:name] = 'string'
|
419
|
+
doc[:name].should == 'string'
|
420
|
+
end
|
421
|
+
|
422
|
+
it "should create key and write value for missing key" do
|
423
|
+
doc = @document.new
|
424
|
+
doc[:foo] = 'string'
|
425
|
+
doc.class.keys.include?('foo').should be_truthy
|
426
|
+
doc[:foo].should == 'string'
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should share the new key with the class" do
|
430
|
+
doc = @document.new
|
431
|
+
doc[:foo] = 'string'
|
432
|
+
@document.keys.should include('foo')
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
context "reading a key" do
|
438
|
+
it "should work for defined keys" do
|
439
|
+
doc = @document.new(:name => 'string')
|
440
|
+
doc.name.should == 'string'
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should raise no method error for undefined keys" do
|
444
|
+
doc = @document.new
|
445
|
+
lambda { doc.fart }.should raise_error(NoMethodError)
|
446
|
+
end
|
447
|
+
|
448
|
+
it "should be accessible for use in the model" do
|
449
|
+
@document.class_eval do
|
450
|
+
def name_and_age
|
451
|
+
"#{self[:name]} (#{self[:age]})"
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
doc = @document.new(:name => 'John', :age => 27)
|
456
|
+
doc.name_and_age.should == 'John (27)'
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should set instance variable" do
|
460
|
+
@document.key :foo, Array
|
461
|
+
doc = @document.new
|
462
|
+
doc.instance_variable_get("@foo").should be_nil
|
463
|
+
doc.foo
|
464
|
+
doc.instance_variable_get("@foo").should == []
|
465
|
+
end
|
466
|
+
|
467
|
+
it "should be overrideable by modules" do
|
468
|
+
@document = Doc do
|
469
|
+
key :other_child, String
|
470
|
+
end
|
471
|
+
|
472
|
+
child = @document.new
|
473
|
+
child.other_child.should be_nil
|
474
|
+
|
475
|
+
@document.send :include, KeyOverride
|
476
|
+
|
477
|
+
overriden_child = @document.new
|
478
|
+
overriden_child.other_child.should == 'special result'
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
context "reading a key before typcasting" do
|
483
|
+
it "should work for defined keys" do
|
484
|
+
doc = @document.new(:name => 12)
|
485
|
+
doc.name_before_type_cast.should == 12
|
486
|
+
end
|
487
|
+
|
488
|
+
it "should raise no method error for undefined keys" do
|
489
|
+
doc = @document.new
|
490
|
+
lambda { doc.foo_before_type_cast }.should raise_error(NoMethodError)
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should be accessible for use in a document" do
|
494
|
+
doc = @document.new(:name => 12)
|
495
|
+
doc.name.should == '12'
|
496
|
+
doc.name_before_type_cast.should == 12
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
context "writing a key" do
|
501
|
+
it "should work for defined keys" do
|
502
|
+
doc = @document.new
|
503
|
+
doc.name = 'John'
|
504
|
+
doc.name.should == 'John'
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should raise no method error for undefined keys" do
|
508
|
+
doc = @document.new
|
509
|
+
lambda { doc.fart = 'poof!' }.should raise_error(NoMethodError)
|
510
|
+
end
|
511
|
+
|
512
|
+
it "should type cast value" do
|
513
|
+
doc = @document.new
|
514
|
+
doc.name = 1234
|
515
|
+
doc.name.should == '1234'
|
516
|
+
doc.age = '21'
|
517
|
+
doc.age.should == 21
|
518
|
+
end
|
519
|
+
|
520
|
+
it "should be accessible for use in the model" do
|
521
|
+
@document.class_eval do
|
522
|
+
def name_and_age=(new_value)
|
523
|
+
new_value.match(/([^\(\s]+) \((.*)\)/)
|
524
|
+
write_key :name, $1
|
525
|
+
write_key :age, $2
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
doc = @document.new
|
530
|
+
doc.name_and_age = 'Frank (62)'
|
531
|
+
doc.name.should == 'Frank'
|
532
|
+
doc.age.should == 62
|
533
|
+
end
|
534
|
+
|
535
|
+
it "should be overrideable by modules" do
|
536
|
+
@document = Doc do
|
537
|
+
key :other_child, String
|
538
|
+
end
|
539
|
+
|
540
|
+
child = @document.new(:other_child => 'foo')
|
541
|
+
child.other_child.should == 'foo'
|
542
|
+
|
543
|
+
@document.send :include, KeyOverride
|
544
|
+
|
545
|
+
overriden_child = @document.new(:other_child => 'foo')
|
546
|
+
overriden_child.other_child.should == 'foo modified'
|
547
|
+
end
|
548
|
+
end # writing a key
|
549
|
+
|
550
|
+
context "checking if a keys value is present" do
|
551
|
+
it "should work for defined keys" do
|
552
|
+
doc = @document.new
|
553
|
+
doc.name?.should be_falsey
|
554
|
+
doc.name = 'John'
|
555
|
+
doc.name?.should be_truthy
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should raise no method error for undefined keys" do
|
559
|
+
doc = @document.new
|
560
|
+
lambda { doc.fart? }.should raise_error(NoMethodError)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
context "equality" do
|
565
|
+
before do
|
566
|
+
@oid = MarkLogic::ObjectId.new
|
567
|
+
end
|
568
|
+
|
569
|
+
it "should delegate hash to _id" do
|
570
|
+
doc = @document.new
|
571
|
+
doc.hash.should == doc._id.hash
|
572
|
+
end
|
573
|
+
|
574
|
+
it "should delegate eql to ==" do
|
575
|
+
doc = @document.new
|
576
|
+
other = @document.new
|
577
|
+
doc.eql?(other).should == (doc == other)
|
578
|
+
doc.eql?(doc).should == (doc == doc)
|
579
|
+
end
|
580
|
+
|
581
|
+
it "should know if same object as another" do
|
582
|
+
doc = @document.new
|
583
|
+
doc.should equal(doc)
|
584
|
+
doc.should_not equal(@document.new)
|
585
|
+
end
|
586
|
+
|
587
|
+
it "should allow set operations on array of documents" do
|
588
|
+
doc = @document.new
|
589
|
+
([doc] & [doc]).should == [doc]
|
590
|
+
end
|
591
|
+
|
592
|
+
it "should be equal if id and class are the same" do
|
593
|
+
(@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be_truthy
|
594
|
+
end
|
595
|
+
|
596
|
+
it "should not be equal if class same but id different" do
|
597
|
+
(@document.new('_id' => @oid) == @document.new('_id' => MarkLogic::ObjectId.new)).should be_falsey
|
598
|
+
end
|
599
|
+
|
600
|
+
it "should not be equal if id same but class different" do
|
601
|
+
another_document = Doc()
|
602
|
+
(@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be_falsey
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
context "reading keys with default values" do
|
607
|
+
before do
|
608
|
+
@document = EDoc do
|
609
|
+
key :name, String, :default => 'foo'
|
610
|
+
key :age, Integer, :default => 20
|
611
|
+
key :net_worth, Float, :default => 100.00
|
612
|
+
key :active, Boolean, :default => true
|
613
|
+
key :smart, Boolean, :default => false
|
614
|
+
key :skills, Array, :default => [1]
|
615
|
+
key :options, Hash, :default => {'foo' => 'bar'}
|
616
|
+
end
|
617
|
+
|
618
|
+
@doc = @document.new
|
619
|
+
end
|
620
|
+
|
621
|
+
it "should work for strings" do
|
622
|
+
@doc.name.should == 'foo'
|
623
|
+
end
|
624
|
+
|
625
|
+
it "should work for integers" do
|
626
|
+
@doc.age.should == 20
|
627
|
+
end
|
628
|
+
|
629
|
+
it "should work for floats" do
|
630
|
+
@doc.net_worth.should == 100.00
|
631
|
+
end
|
632
|
+
|
633
|
+
it "should work for booleans" do
|
634
|
+
@doc.active.should == true
|
635
|
+
@doc.smart.should == false
|
636
|
+
end
|
637
|
+
|
638
|
+
it "should work for arrays" do
|
639
|
+
@doc.skills.should == [1]
|
640
|
+
@doc.skills << 2
|
641
|
+
@doc.skills.should == [1, 2]
|
642
|
+
end
|
643
|
+
|
644
|
+
it "should work for hashes" do
|
645
|
+
@doc.options['foo'].should == 'bar'
|
646
|
+
@doc.options['baz'] = 'wick'
|
647
|
+
@doc.options['baz'].should == 'wick'
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
context "#save!" do
|
652
|
+
before do
|
653
|
+
@root = DocWithAValidation.create(:name => "Root")
|
654
|
+
@doc = @root.e_doc_with_a_validations.build :name => "Embedded"
|
655
|
+
end
|
656
|
+
|
657
|
+
it "should should save when valid" do
|
658
|
+
@doc.save!
|
659
|
+
@root.reload.e_doc_with_a_validations.first.should == @doc
|
660
|
+
end
|
661
|
+
|
662
|
+
it "should should raise errors when invalid" do
|
663
|
+
@doc.name = ''
|
664
|
+
expect { @doc.save! }.to raise_error(MarkMapper::DocumentNotValid)
|
665
|
+
end
|
666
|
+
|
667
|
+
it "should should raise errors when root document is invalid" do
|
668
|
+
@root.name = ''
|
669
|
+
@root.save(:validate => false)
|
670
|
+
expect{ @doc.save! }.to raise_error(MarkMapper::DocumentNotValid)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end # instance of a embedded document
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|