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.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +39 -0
  4. data/examples/attr_accessible.rb +24 -0
  5. data/examples/attr_protected.rb +24 -0
  6. data/examples/cache_key.rb +26 -0
  7. data/examples/custom_types.rb +26 -0
  8. data/examples/identity_map.rb +30 -0
  9. data/examples/identity_map/automatic.rb +2 -0
  10. data/examples/keys.rb +42 -0
  11. data/examples/modifiers/set.rb +27 -0
  12. data/examples/plugins.rb +40 -0
  13. data/examples/querying.rb +39 -0
  14. data/examples/sample_app.rb +43 -0
  15. data/examples/scopes.rb +56 -0
  16. data/examples/validating/embedded_docs.rb +31 -0
  17. data/lib/mark_mapper.rb +125 -0
  18. data/lib/mark_mapper/config.rb +90 -0
  19. data/lib/mark_mapper/connection.rb +60 -0
  20. data/lib/mark_mapper/criteria_hash.rb +194 -0
  21. data/lib/mark_mapper/document.rb +46 -0
  22. data/lib/mark_mapper/embedded_document.rb +32 -0
  23. data/lib/mark_mapper/exceptions.rb +33 -0
  24. data/lib/mark_mapper/extensions/array.rb +27 -0
  25. data/lib/mark_mapper/extensions/boolean.rb +45 -0
  26. data/lib/mark_mapper/extensions/date.rb +29 -0
  27. data/lib/mark_mapper/extensions/duplicable.rb +86 -0
  28. data/lib/mark_mapper/extensions/float.rb +18 -0
  29. data/lib/mark_mapper/extensions/hash.rb +26 -0
  30. data/lib/mark_mapper/extensions/integer.rb +27 -0
  31. data/lib/mark_mapper/extensions/kernel.rb +11 -0
  32. data/lib/mark_mapper/extensions/nil_class.rb +18 -0
  33. data/lib/mark_mapper/extensions/object.rb +30 -0
  34. data/lib/mark_mapper/extensions/object_id.rb +18 -0
  35. data/lib/mark_mapper/extensions/set.rb +20 -0
  36. data/lib/mark_mapper/extensions/string.rb +31 -0
  37. data/lib/mark_mapper/extensions/symbol.rb +87 -0
  38. data/lib/mark_mapper/extensions/time.rb +29 -0
  39. data/lib/mark_mapper/locale/en.yml +5 -0
  40. data/lib/mark_mapper/middleware/identity_map.rb +41 -0
  41. data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
  42. data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
  43. data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
  44. data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
  45. data/lib/mark_mapper/normalizers/integer.rb +19 -0
  46. data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
  47. data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
  48. data/lib/mark_mapper/options_hash.rb +103 -0
  49. data/lib/mark_mapper/pagination.rb +6 -0
  50. data/lib/mark_mapper/pagination/collection.rb +32 -0
  51. data/lib/mark_mapper/pagination/paginator.rb +46 -0
  52. data/lib/mark_mapper/plugins.rb +22 -0
  53. data/lib/mark_mapper/plugins/accessible.rb +61 -0
  54. data/lib/mark_mapper/plugins/active_model.rb +18 -0
  55. data/lib/mark_mapper/plugins/associations.rb +96 -0
  56. data/lib/mark_mapper/plugins/associations/base.rb +98 -0
  57. data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
  58. data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
  59. data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  60. data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
  61. data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
  62. data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
  63. data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
  64. data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  65. data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
  66. data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  67. data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  68. data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  69. data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
  70. data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
  71. data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  72. data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  73. data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
  74. data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
  75. data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
  76. data/lib/mark_mapper/plugins/caching.rb +21 -0
  77. data/lib/mark_mapper/plugins/callbacks.rb +42 -0
  78. data/lib/mark_mapper/plugins/clone.rb +24 -0
  79. data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
  80. data/lib/mark_mapper/plugins/dirty.rb +61 -0
  81. data/lib/mark_mapper/plugins/document.rb +41 -0
  82. data/lib/mark_mapper/plugins/dumpable.rb +22 -0
  83. data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
  84. data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  85. data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
  86. data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
  87. data/lib/mark_mapper/plugins/equality.rb +23 -0
  88. data/lib/mark_mapper/plugins/identity_map.rb +144 -0
  89. data/lib/mark_mapper/plugins/indexable.rb +86 -0
  90. data/lib/mark_mapper/plugins/inspect.rb +16 -0
  91. data/lib/mark_mapper/plugins/keys.rb +470 -0
  92. data/lib/mark_mapper/plugins/keys/key.rb +134 -0
  93. data/lib/mark_mapper/plugins/keys/static.rb +45 -0
  94. data/lib/mark_mapper/plugins/logger.rb +18 -0
  95. data/lib/mark_mapper/plugins/modifiers.rb +140 -0
  96. data/lib/mark_mapper/plugins/pagination.rb +16 -0
  97. data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
  98. data/lib/mark_mapper/plugins/persistence.rb +79 -0
  99. data/lib/mark_mapper/plugins/protected.rb +45 -0
  100. data/lib/mark_mapper/plugins/querying.rb +173 -0
  101. data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
  102. data/lib/mark_mapper/plugins/rails.rb +79 -0
  103. data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  104. data/lib/mark_mapper/plugins/sci.rb +82 -0
  105. data/lib/mark_mapper/plugins/scopes.rb +28 -0
  106. data/lib/mark_mapper/plugins/serialization.rb +109 -0
  107. data/lib/mark_mapper/plugins/timestamps.rb +29 -0
  108. data/lib/mark_mapper/plugins/touch.rb +18 -0
  109. data/lib/mark_mapper/plugins/userstamps.rb +18 -0
  110. data/lib/mark_mapper/plugins/validations.rb +96 -0
  111. data/lib/mark_mapper/query.rb +278 -0
  112. data/lib/mark_mapper/railtie.rb +52 -0
  113. data/lib/mark_mapper/railtie/database.rake +65 -0
  114. data/lib/mark_mapper/translation.rb +10 -0
  115. data/lib/mark_mapper/version.rb +4 -0
  116. data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
  117. data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
  118. data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
  119. data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
  120. data/spec/config/mark_mapper.yml +6 -0
  121. data/spec/examples_spec.rb +25 -0
  122. data/spec/functional/accessible_spec.rb +198 -0
  123. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
  124. data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
  125. data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
  126. data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
  127. data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
  128. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
  129. data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
  130. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
  131. data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
  132. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
  133. data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
  134. data/spec/functional/associations/one_proxy_spec.rb +406 -0
  135. data/spec/functional/associations_spec.rb +48 -0
  136. data/spec/functional/caching_spec.rb +75 -0
  137. data/spec/functional/callbacks_spec.rb +330 -0
  138. data/spec/functional/counter_cache_spec.rb +235 -0
  139. data/spec/functional/dirty_spec.rb +316 -0
  140. data/spec/functional/document_spec.rb +310 -0
  141. data/spec/functional/dumpable_spec.rb +24 -0
  142. data/spec/functional/dynamic_querying_spec.rb +75 -0
  143. data/spec/functional/embedded_document_spec.rb +316 -0
  144. data/spec/functional/equality_spec.rb +20 -0
  145. data/spec/functional/extensions_spec.rb +16 -0
  146. data/spec/functional/identity_map_spec.rb +483 -0
  147. data/spec/functional/keys_spec.rb +339 -0
  148. data/spec/functional/logger_spec.rb +20 -0
  149. data/spec/functional/modifiers_spec.rb +446 -0
  150. data/spec/functional/options_hash_spec.rb +41 -0
  151. data/spec/functional/pagination_spec.rb +89 -0
  152. data/spec/functional/partial_updates_spec.rb +530 -0
  153. data/spec/functional/protected_spec.rb +199 -0
  154. data/spec/functional/querying_spec.rb +984 -0
  155. data/spec/functional/rails_spec.rb +55 -0
  156. data/spec/functional/sci_spec.rb +374 -0
  157. data/spec/functional/scopes_spec.rb +204 -0
  158. data/spec/functional/static_keys_spec.rb +153 -0
  159. data/spec/functional/timestamps_spec.rb +97 -0
  160. data/spec/functional/touch_spec.rb +125 -0
  161. data/spec/functional/userstamps_spec.rb +46 -0
  162. data/spec/functional/validations_spec.rb +416 -0
  163. data/spec/quality_spec.rb +51 -0
  164. data/spec/spec_helper.rb +150 -0
  165. data/spec/support/matchers.rb +15 -0
  166. data/spec/support/models.rb +256 -0
  167. data/spec/symbol_operator_spec.rb +70 -0
  168. data/spec/symbol_spec.rb +9 -0
  169. data/spec/unit/associations/base_spec.rb +146 -0
  170. data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
  171. data/spec/unit/associations/many_association_spec.rb +64 -0
  172. data/spec/unit/associations/one_association_spec.rb +48 -0
  173. data/spec/unit/associations/proxy_spec.rb +103 -0
  174. data/spec/unit/clone_spec.rb +79 -0
  175. data/spec/unit/config_generator_spec.rb +24 -0
  176. data/spec/unit/criteria_hash_spec.rb +218 -0
  177. data/spec/unit/document_spec.rb +251 -0
  178. data/spec/unit/dynamic_finder_spec.rb +125 -0
  179. data/spec/unit/embedded_document_spec.rb +676 -0
  180. data/spec/unit/equality_spec.rb +38 -0
  181. data/spec/unit/exceptions_spec.rb +12 -0
  182. data/spec/unit/extensions_spec.rb +368 -0
  183. data/spec/unit/identity_map_middleware_spec.rb +134 -0
  184. data/spec/unit/inspect_spec.rb +47 -0
  185. data/spec/unit/key_spec.rb +276 -0
  186. data/spec/unit/keys_spec.rb +155 -0
  187. data/spec/unit/mark_mapper_spec.rb +37 -0
  188. data/spec/unit/model_generator_spec.rb +45 -0
  189. data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
  190. data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
  191. data/spec/unit/normalizers/fields_value_spec.rb +45 -0
  192. data/spec/unit/normalizers/hash_key_spec.rb +15 -0
  193. data/spec/unit/normalizers/integer_spec.rb +24 -0
  194. data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
  195. data/spec/unit/normalizers/sort_value_spec.rb +98 -0
  196. data/spec/unit/options_hash_spec.rb +64 -0
  197. data/spec/unit/pagination/collection_spec.rb +30 -0
  198. data/spec/unit/pagination/paginator_spec.rb +118 -0
  199. data/spec/unit/pagination_spec.rb +11 -0
  200. data/spec/unit/plugins_spec.rb +89 -0
  201. data/spec/unit/query_spec.rb +837 -0
  202. data/spec/unit/rails_compatibility_spec.rb +40 -0
  203. data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
  204. data/spec/unit/rails_spec.rb +188 -0
  205. data/spec/unit/serialization_spec.rb +169 -0
  206. data/spec/unit/serializers/json_serializer_spec.rb +218 -0
  207. data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
  208. data/spec/unit/time_zones_spec.rb +44 -0
  209. data/spec/unit/translation_spec.rb +27 -0
  210. data/spec/unit/validations_spec.rb +588 -0
  211. metadata +307 -0
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Clone" do
4
+ context "Document" do
5
+ before do
6
+ @document = Doc()
7
+ @embedded = EDoc()
8
+ @document.many :widgets, :class => @embedded
9
+ @tags = ['red', 'green', 'blue']
10
+ @doc = @document.create({
11
+ :name => "foo",
12
+ :age => 27,
13
+ :tags => @tags,
14
+ :widgets => [@embedded.new, @embedded.new],
15
+ })
16
+ end
17
+
18
+ context "#clone" do
19
+ it "should be new" do
20
+ @doc.clone.should be_new
21
+ end
22
+
23
+ it "should copy the attributes" do
24
+ clone = @doc.clone
25
+ clone.name.should == "foo"
26
+ clone.age.should == 27
27
+ end
28
+
29
+ it "should clone duplicable attributes" do
30
+ @doc.clone.tags.should_not equal(@tags)
31
+ end
32
+
33
+ it "should clone many embedded documents" do
34
+ @doc.clone.widgets.object_id.should_not equal(@doc.widgets.object_id)
35
+ end
36
+
37
+ it "should not be destroyed" do
38
+ @doc.destroy
39
+ @doc.clone.should_not be_destroyed
40
+ end
41
+
42
+ it "should generate a new id" do
43
+ @doc.clone.id.should_not be_nil
44
+ @doc.clone.id.should_not equal(@doc.id)
45
+ end
46
+
47
+ it "should clone a cloned document" do
48
+ expect { @doc.clone.clone }.to_not raise_error
49
+ @doc.clone.clone.id.should be_a MarkLogic::ObjectId
50
+ end
51
+ end
52
+ end
53
+
54
+ context "EmbeddedDocument" do
55
+ before do
56
+ @document = EDoc do
57
+ key :name, String
58
+ key :age, Integer
59
+ end
60
+ end
61
+
62
+ context "#clone" do
63
+ it "should regenerate the id" do
64
+ doc = @document.new(:name => "foo", :age => 27)
65
+ doc_id = doc.id
66
+ clone = doc.clone
67
+ clone_id = clone.id
68
+ clone_id.should_not == doc_id
69
+ end
70
+
71
+ it "should copy the attributes" do
72
+ doc = @document.new(:name => "foo", :age => 27)
73
+ clone = doc.clone
74
+ clone.name.should == "foo"
75
+ clone.age.should == 27
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ # require 'spec_helper'
2
+ # require 'rails/generators'
3
+ # require 'rails/generators/test_case'
4
+ # require 'rails/generators/mark_mapper/config/config_generator'
5
+
6
+ # describe MarkMapper::Generators::ConfigGenerator do
7
+ # include GeneratorSpec::TestCase
8
+
9
+ # destination File.expand_path('../../tmp', File.dirname(__FILE__))
10
+ # before do
11
+ # prepare_destination
12
+ # end
13
+
14
+ # it 'marklogic.yml are properly created' do
15
+ # run_generator
16
+ # assert_file 'config/marklogic.yml', /#{File.basename(destination_root)}/
17
+ # end
18
+
19
+ # it 'marklogic.yml are properly created with defined database_name' do
20
+ # run_generator %w{dummy}
21
+ # assert_file 'config/marklogic.yml', /dummy/
22
+ # end
23
+
24
+ # end
@@ -0,0 +1,218 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ describe MarkMapper::CriteriaHash do
5
+ context "#initialize_copy" do
6
+ before do
7
+ @original = described_class.new({
8
+ :comments => {:_id => 1}, :tags => ['marklogic', 'ruby'],
9
+ }, :object_ids => [:_id])
10
+ @cloned = @original.clone
11
+ end
12
+
13
+ it "duplicates source hash" do
14
+ @cloned.source.should_not equal(@original.source)
15
+ end
16
+
17
+ it "duplicates options hash" do
18
+ @cloned.options.should_not equal(@original.options)
19
+ end
20
+
21
+ it "clones duplicable? values" do
22
+ @cloned[:comments].should_not equal(@original[:comments])
23
+ @cloned[:tags].should_not equal(@original[:tags])
24
+ end
25
+ end
26
+
27
+ context "#object_ids=" do
28
+ it "works with array" do
29
+ criteria = described_class.new
30
+ criteria.object_ids = [:_id]
31
+ criteria.object_ids.should == [:_id]
32
+ end
33
+
34
+ it "flattens multi-dimensional array" do
35
+ criteria = described_class.new
36
+ criteria.object_ids = [[:_id]]
37
+ criteria.object_ids.should == [:_id]
38
+ end
39
+
40
+ it "raises argument error if not array" do
41
+ expect { described_class.new.object_ids = {} }.to raise_error(ArgumentError)
42
+ expect { described_class.new.object_ids = nil }.to raise_error(ArgumentError)
43
+ expect { described_class.new.object_ids = 'foo' }.to raise_error(ArgumentError)
44
+ end
45
+ end
46
+
47
+ context "#[]=" do
48
+ context "with key and value" do
49
+ let(:key_normalizer) { lambda { |*args| :normalized_key } }
50
+ let(:value_normalizer) { lambda { |*args| 'normalized_value' } }
51
+
52
+ it "sets normalized key to normalized value in source" do
53
+ criteria = described_class.new({}, :value_normalizer => value_normalizer, :key_normalizer => key_normalizer)
54
+ criteria[:foo] = 'bar'
55
+ criteria.source[:normalized_key].should eq('normalized_value')
56
+ end
57
+ end
58
+
59
+ context "with conditions" do
60
+ it "sets each of conditions keys in source" do
61
+ criteria = described_class.new
62
+ criteria[:conditions] = {:_id => 'john', :foo => 'bar'}
63
+ criteria.source[:_id].should eq('john')
64
+ criteria.source[:foo].should eq('bar')
65
+ end
66
+ end
67
+
68
+ context "with symbol operators" do
69
+ it "sets nests key with operator and value" do
70
+ criteria = described_class.new
71
+ criteria[:age.gt] = 20
72
+ criteria[:age.lt] = 10
73
+ criteria.source[:age].should eq({:$gt => 20, :$lt => 10})
74
+ end
75
+ end
76
+ end
77
+
78
+ context "#merge" do
79
+ it "works when no keys match" do
80
+ c1 = described_class.new(:foo => 'bar')
81
+ c2 = described_class.new(:baz => 'wick')
82
+ c1.merge(c2).source.should eq(:foo => 'bar', :baz => 'wick')
83
+ end
84
+
85
+ it "turns matching keys with simple values into array" do
86
+ c1 = described_class.new(:foo => 'bar')
87
+ c2 = described_class.new(:foo => 'baz')
88
+ c1.merge(c2).source.should eq(:foo => {:$eq => %w[bar baz]})
89
+ end
90
+
91
+ it "uniques matching key values" do
92
+ c1 = described_class.new(:foo => 'bar')
93
+ c2 = described_class.new(:foo => 'bar')
94
+ c1.merge(c2).source.should eq(:foo => {:$eq => %w[bar]})
95
+ end
96
+
97
+ it "correctly merges arrays and non-arrays" do
98
+ c1 = described_class.new(:foo => 'bar')
99
+ c2 = described_class.new(:foo => %w[bar baz])
100
+ c1.merge(c2).source.should eq(:foo => {:$eq => %w[bar baz]})
101
+ c2.merge(c1).source.should eq(:foo => {:$eq => %w[bar baz]})
102
+ end
103
+
104
+ it "correctly merges two bson object ids" do
105
+ id1 = SecureRandom.hex
106
+ id2 = SecureRandom.hex
107
+ c1 = described_class.new(:foo => id1)
108
+ c2 = described_class.new(:foo => id2)
109
+ c1.merge(c2).source.should eq(:foo => {:$eq => [id1, id2]})
110
+ end
111
+
112
+ it "correctly merges array and an object id" do
113
+ id1 = SecureRandom.hex
114
+ id2 = SecureRandom.hex
115
+ c1 = described_class.new(:foo => [id1])
116
+ c2 = described_class.new(:foo => id2)
117
+ c1.merge(c2).source.should eq(:foo => {:$eq => [id1, id2]})
118
+ c2.merge(c1).source.should eq(:foo => {:$eq => [id1, id2]})
119
+ end
120
+
121
+ it "is able to merge two modifier hashes" do
122
+ c1 = described_class.new(:$eq => [1, 2])
123
+ c2 = described_class.new(:$eq => [2, 3])
124
+ c1.merge(c2).source.should eq(:$eq => [1, 2, 3])
125
+ end
126
+
127
+ it "is able to merge two modifier hashes with hash values" do
128
+ c1 = described_class.new(:arr => {:$elemMatch => {:foo => 'bar'}})
129
+ c2 = described_class.new(:arr => {:$elemMatch => {:omg => 'ponies'}})
130
+ c1.merge(c2).source.should eq(:arr => {:$elemMatch => {:foo => 'bar', :omg => 'ponies'}})
131
+ end
132
+
133
+ it "merges matching keys with a single modifier" do
134
+ c1 = described_class.new(:foo => {:$eq => [1, 2, 3]})
135
+ c2 = described_class.new(:foo => {:$eq => [1, 4, 5]})
136
+ c1.merge(c2).source.should eq(:foo => {:$eq => [1, 2, 3, 4, 5]})
137
+ end
138
+
139
+ it "merges matching keys with multiple modifiers" do
140
+ c1 = described_class.new(:foo => {:$eq => [1, 2, 3]})
141
+ c2 = described_class.new(:foo => {:$all => [1, 4, 5]})
142
+ c1.merge(c2).source.should eq(:foo => {:$eq => [1, 2, 3], :$all => [1, 4, 5]})
143
+ end
144
+
145
+ it "does not update mergee" do
146
+ c1 = described_class.new(:foo => 'bar')
147
+ c2 = described_class.new(:foo => 'baz')
148
+ c1.merge(c2).should_not equal(c1)
149
+ c1[:foo].should == 'bar'
150
+ end
151
+
152
+ context "given multiple $or clauses" do
153
+ before do
154
+ @c1 = described_class.new(:$or => [{:a => 1}, {:b => 2}])
155
+ @c2 = described_class.new(:$or => [{:a => 3}, {:b => 4}])
156
+ @c3 = described_class.new(:$or => [{:a => 4}, {:b => 4}])
157
+ end
158
+
159
+ it "merges two $ors into a compound $and" do
160
+ merged = @c1.merge(@c2)
161
+ merged[:$and].should == [
162
+ {:$or => [{:a => 1}, {:b => 2}]},
163
+ {:$or => [{:a => 3}, {:b => 4}]}
164
+ ]
165
+ end
166
+
167
+ it "merges an $and and a $or into a compound $and" do
168
+ merged = @c1.merge(@c2).merge(@c3)
169
+ merged[:$and].should == [
170
+ {:$or => [{:a => 1}, {:b => 2}]},
171
+ {:$or => [{:a => 3}, {:b => 4}]},
172
+ {:$or => [{:a => 4}, {:b => 4}]}
173
+ ]
174
+ end
175
+
176
+ it "merges an $or and an $and into a compound $and" do
177
+ merged = @c3.merge @c1.merge(@c2)
178
+ merged[:$and].should == [
179
+ {:$or => [{:a => 1}, {:b => 2}]},
180
+ {:$or => [{:a => 3}, {:b => 4}]},
181
+ {:$or => [{:a => 4}, {:b => 4}]}
182
+ ]
183
+ end
184
+ end
185
+ end
186
+
187
+ context "#merge!" do
188
+ it "updates mergee" do
189
+ c1 = described_class.new(:foo => 'bar')
190
+ c2 = described_class.new(:foo => 'baz')
191
+ c1.merge!(c2).should equal(c1)
192
+ c1[:foo].should == {:$eq => ['bar', 'baz']}
193
+ end
194
+ end
195
+
196
+ context "#simple?" do
197
+ it "returns true if only filtering by _id" do
198
+ described_class.new(:_id => 'id').should be_simple
199
+ end
200
+
201
+ it "returns true if only filtering by Sci" do
202
+ described_class.new(:_id => 'id', :_type => 'Foo').should be_simple
203
+ described_class.new(:_type => 'Foo', :_id => 'id').should be_simple # reverse order
204
+ end
205
+
206
+ it "returns false if querying by more than max number of simple keys" do
207
+ described_class.new(:one => 1, :two => 2, :three => 3).should_not be_simple
208
+ end
209
+
210
+ it "returns false if querying by anthing other than _id/Sci" do
211
+ described_class.new(:foo => 'bar').should_not be_simple
212
+ end
213
+
214
+ it "returns false if querying only by _type" do
215
+ described_class.new(:_type => 'Foo').should_not be_simple
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,251 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "Document" do
5
+ context "The Document Class" do
6
+ before do
7
+ @document = Doc()
8
+ end
9
+
10
+ it "should return false for embeddable" do
11
+ Doc().embeddable?.should be_falsey
12
+ end
13
+
14
+ it "should have logger method" do
15
+ @document.logger.should == MarkMapper.logger
16
+ @document.logger.should be_instance_of(Logger)
17
+ end
18
+
19
+ it "should use default database by default" do
20
+ @document.database.should == MarkMapper.application.content_databases[0]
21
+ end
22
+
23
+ it "should have a connection" do
24
+ @document.connection.should be_instance_of(MarkLogic::Connection)
25
+ end
26
+
27
+ it "should allow setting different connection without affecting the default" do
28
+ conn = MarkLogic::Connection.new(HOST, PORT)
29
+ @document.connection conn
30
+ @document.connection.should be conn
31
+ @document.connection.should_not be MarkMapper.connection
32
+ end
33
+
34
+ it "should allow setting a different database without affecting the default" do
35
+ db = MarkLogic::Database.new('test2', CONNECTION)
36
+ @document.database = db
37
+ @document.database.should == db
38
+ @document.database_name.should == 'test2'
39
+ @document.database.database_name.should == 'test2'
40
+
41
+ another_document = Doc()
42
+ another_document.database.database_name.should == MarkMapper.application.content_databases[0].database_name
43
+ end
44
+
45
+ it "should allow setting the collection name" do
46
+ @document.set_collection_name('foobar')
47
+ @document.collection.name.should == 'foobar'
48
+ end
49
+
50
+ context ".collection" do
51
+ it "should default collection name to class name tableized" do
52
+ class ::Item
53
+ include MarkMapper::Document
54
+ end.collection.name.should == 'items'
55
+ end
56
+
57
+ it "should default collection name of namespaced class to tableized with dot separation" do
58
+ module ::BloggyPoo
59
+ class Post
60
+ include MarkMapper::Document
61
+ end.collection.name.should == 'bloggy_poo.posts'
62
+ end
63
+ end
64
+
65
+ it "should be an instance of a MarkLogic::Collection" do
66
+ @document.collection.should be_instance_of(MarkLogic::Collection)
67
+ end
68
+ end
69
+ end # Document class
70
+
71
+ context "Documents that inherit from other documents" do
72
+ it "should default collection name to inherited class" do
73
+ Message.collection_name.should == 'messages'
74
+ Enter.collection_name.should == 'messages'
75
+ Exit.collection_name.should == 'messages'
76
+ Chat.collection_name.should == 'messages'
77
+ end
78
+
79
+ it "should default associations to inherited class" do
80
+ Message.associations.keys.should include(:room)
81
+ Enter.associations.keys.should include(:room)
82
+ Exit.associations.keys.should include(:room)
83
+ Chat.associations.keys.should include(:room)
84
+ end
85
+ end
86
+
87
+ context "descendants" do
88
+ it "should default to an empty array" do
89
+ Enter.descendants.should == []
90
+ end
91
+
92
+ it "should be recorded" do
93
+ Message.descendants.should == [Enter, Exit, Chat]
94
+ end
95
+ end
96
+
97
+ context "An instance of a document" do
98
+ before do
99
+ @document = Doc do
100
+ key :name, String
101
+ key :age, Integer
102
+ end
103
+ end
104
+
105
+ it "should respond to cache_key" do
106
+ @document.new.should respond_to(:cache_key)
107
+ end
108
+
109
+ it "should create id during initialization" do
110
+ @document.new._id.should be_instance_of(MarkLogic::ObjectId)
111
+ end
112
+
113
+ it "should have access to logger" do
114
+ doc = @document.new
115
+ doc.logger.should == @document.logger
116
+ doc.logger.should be_instance_of(Logger)
117
+ end
118
+
119
+ it "should have access to the class's collection" do
120
+ doc = @document.new
121
+ doc.collection.name.should == @document.collection.name
122
+ end
123
+
124
+ it "should use default values if defined for keys" do
125
+ @document.key :active, Boolean, :default => true
126
+
127
+ @document.new.active.should be_truthy
128
+ @document.new(:active => false).active.should be_falsey
129
+ end
130
+
131
+ it "should use default values if defined even when custom data type" do
132
+ @document.key :window, WindowSize, :default => WindowSize.new(600, 480)
133
+
134
+ doc = @document.new
135
+ doc.window.should == WindowSize.new(600, 480)
136
+ end
137
+
138
+ context "root document" do
139
+ it "should set self to the root document on embedded documents" do
140
+ klass = Doc()
141
+ pets = EDoc()
142
+
143
+ klass.many :pets, :class => pets
144
+
145
+ doc = klass.new(:pets => [{}])
146
+ doc.pets.first._root_document.should == doc
147
+ end
148
+ end
149
+
150
+ context "new?" do
151
+ it "should be true if no id" do
152
+ @document.new.new?.should be_truthy
153
+ end
154
+
155
+ it "should be true if id but using custom id and not saved yet" do
156
+ @document.key :_id, String
157
+ doc = silence_stderr { @document.new }
158
+ doc.id = '1234'
159
+ doc.new?.should be_truthy
160
+ end
161
+ end
162
+
163
+ context "equality" do
164
+ before do
165
+ @oid = MarkLogic::ObjectId.new
166
+ end
167
+
168
+ it "should delegate hash to _id" do
169
+ doc = @document.new
170
+ doc.hash.should == doc._id.hash
171
+ end
172
+
173
+ it "should delegate eql to ==" do
174
+ doc = @document.new
175
+ other = @document.new
176
+ doc.eql?(other).should == (doc == other)
177
+ doc.eql?(doc).should == (doc == doc)
178
+ end
179
+
180
+ it "should know if same object as another" do
181
+ doc = @document.new
182
+ doc.should equal(doc)
183
+ doc.should_not equal(@document.new)
184
+ end
185
+
186
+ it "should allow set operations on array of documents" do
187
+ @document.key :parent_id, ObjectId
188
+ @document.belongs_to :parent, :class => @document
189
+
190
+ parent = @document.create
191
+ child = @document.create(:parent => parent)
192
+
193
+ ([child.parent] & [parent]).should == [parent]
194
+ end
195
+
196
+ it "should be equal if id and class are the same" do
197
+ (@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be(true)
198
+ end
199
+
200
+ it "should not be equal if class same but id different" do
201
+ (@document.new('_id' => @oid) == @document.new('_id' => MarkLogic::ObjectId.new)).should be(false)
202
+ end
203
+
204
+ it "should not be equal if id same but class different" do
205
+ another_document = Doc()
206
+ (@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be(false)
207
+ end
208
+ end
209
+
210
+ context "nil attributes" do
211
+
212
+ it "should list all the keys and default non nil attributes" do
213
+ doc = @document.new
214
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
215
+ doc.attributes.keys.sort.should == ['_id']
216
+ end
217
+
218
+ it "should list all the keys and non nil attributes" do
219
+ doc = @document.new(:name => "John")
220
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
221
+ doc.attributes.keys.sort.should == ['_id','name']
222
+ end
223
+
224
+ it "should list all the keys and pickup changed nil attributes" do
225
+ doc = @document.new(:name => "John")
226
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
227
+ doc.attributes.keys.sort.should == ['_id','name']
228
+
229
+ doc.name = nil
230
+
231
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
232
+ doc.attributes.keys.sort.should == ['_id']
233
+ end
234
+
235
+ it "should list all the keys and pickup changed nil and non-nil attributes" do
236
+ doc = @document.new(:name => "John")
237
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
238
+ doc.attributes.keys.sort.should == ['_id','name']
239
+
240
+ doc.name = nil
241
+ doc.age = 12
242
+
243
+ doc.keys.keys.sort.should == ['_id', 'age', 'name']
244
+ doc.attributes.keys.sort.should == ['_id','age']
245
+ end
246
+
247
+ end
248
+
249
+ end # instance of a document
250
+ end # DocumentTest
251
+