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,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Inspect" do
4
+ context "#inspect" do
5
+ before do
6
+ @document = Doc('User') do
7
+ key :name, String
8
+ key :age, Integer
9
+ key :email, String
10
+ end
11
+
12
+ @doc = @document.new(:name => 'John', :age => 29)
13
+ end
14
+
15
+ it "should print out non-nil attributes in alpha sorted order" do
16
+ @doc.inspect.should =~ /_id:.*, age: 29, name: "John"/
17
+ end
18
+
19
+ it "should print out all attributes when (optional) include_super argument is true" do
20
+ @doc.inspect(true).should =~ /_id:.*, age: 29, email: nil, name: "John"/
21
+ end
22
+
23
+ it "should include class name" do
24
+ @doc.inspect.should =~ /^#<User/
25
+ end
26
+
27
+ it "should include embedded documents" do
28
+ klass = Doc()
29
+ pets = EDoc()
30
+
31
+ klass.many :pets, :class => pets
32
+
33
+ doc = klass.new(:pets => [{:name => "Kitten"}])
34
+ doc.inspect.should =~ /_id:.*, pets: \[.*_id.*, name: "Kitten".*\]/
35
+ end
36
+
37
+ it "should include embedded document" do
38
+ klass = Doc()
39
+ pet = EDoc()
40
+
41
+ klass.one :pet, :class => pet
42
+
43
+ doc = klass.new(:pet => {:name => "Kitten"})
44
+ doc.inspect.should =~ /_id:.*, pet: .*_id.*, name: "Kitten".*/
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,276 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ class FooType < Struct.new(:bar)
5
+ def self.to_marklogic(value)
6
+ 'to_marklogic'
7
+ end
8
+
9
+ def self.from_marklogic(value)
10
+ 'from_marklogic'
11
+ end
12
+ end
13
+
14
+ describe "Key" do
15
+ Key = MarkMapper::Plugins::Keys::Key
16
+
17
+ context "Initializing a new key" do
18
+ it "should allow setting the name" do
19
+ Key.new(:foo, String).name.should == 'foo'
20
+ end
21
+
22
+ it "should allow setting the type" do
23
+ Key.new(:foo, Integer).type.should be(Integer)
24
+ end
25
+
26
+ it "should allow setting options" do
27
+ Key.new(:foo, Integer, :required => true).options[:required].should be(true)
28
+ end
29
+
30
+ it "should default options to {}" do
31
+ Key.new(:foo, Integer, nil).options.should == {}
32
+ end
33
+
34
+ it "should symbolize option keys" do
35
+ Key.new(:foo, Integer, 'required' => true).options[:required].should be(true)
36
+ end
37
+
38
+ it "should work with just name" do
39
+ key = Key.new(:foo)
40
+ key.name.should == 'foo'
41
+ end
42
+
43
+ it "should work with name and type" do
44
+ key = Key.new(:foo, String)
45
+ key.name.should == 'foo'
46
+ key.type.should == String
47
+ end
48
+
49
+ it "should work with name, type, and options" do
50
+ key = Key.new(:foo, String, :required => true)
51
+ key.name.should == 'foo'
52
+ key.type.should == String
53
+ key.options[:required].should be_truthy
54
+ end
55
+
56
+ it "should work with name and options" do
57
+ key = Key.new(:foo, :required => true)
58
+ key.name.should == 'foo'
59
+ key.options[:required].should be_truthy
60
+ end
61
+
62
+ it "should not permit reserved names" do
63
+ expect { Key.new(:id) }.to raise_error(/reserved/)
64
+ end
65
+
66
+ it "should not permit bad names" do
67
+ expect { Key.new(:"id.bar") }.to raise_error(/must match/)
68
+ end
69
+
70
+ it "should permit bad names if __dynamic" do
71
+ expect { Key.new(:"id.bar", :__dynamic => true) }.to_not raise_error
72
+ end
73
+
74
+ it "should permit bad names if it is not to create accessors" do
75
+ expect { Key.new(:"id.bar", :accessors => :skip) }.to_not raise_error
76
+ end
77
+ end
78
+
79
+ context "A key" do
80
+ it "should be equal to another key with same name and type" do
81
+ Key.new(:name, String).should == Key.new(:name, String)
82
+ end
83
+
84
+ it "should not be equal to another key with different name" do
85
+ Key.new(:name, String).should_not == Key.new(:foo, String)
86
+ end
87
+
88
+ it "should not be equal to another key with different type" do
89
+ Key.new(:name, String).should_not == Key.new(:name, Integer)
90
+ end
91
+
92
+ it "should know if it is a embedded_document" do
93
+ Key.new(:name, EDoc()).embeddable?.should be_truthy
94
+ end
95
+
96
+ it "should know if it is not a embedded_document" do
97
+ Key.new(:name, String).embeddable?.should be_falsey
98
+ end
99
+
100
+ it "should know if it is a number" do
101
+ Key.new(:age, Integer).number?.should be_truthy
102
+ Key.new(:age, Float).number?.should be_truthy
103
+ end
104
+
105
+ it "should know if it is not a number" do
106
+ Key.new(:age, String).number?.should be_falsey
107
+ end
108
+ end
109
+
110
+ context "for an array with :typecast option" do
111
+ before { @key = Key.new(:user_ids, Array, :typecast => 'ObjectId') }
112
+ subject { @key }
113
+
114
+ it "should cast each element correctly" do
115
+ ids = [MarkLogic::ObjectId.new, MarkLogic::ObjectId.new, MarkLogic::ObjectId.new.to_s, MarkLogic::ObjectId.new.to_s]
116
+ subject.set(ids).should == ids.map { |id| ObjectId.to_marklogic(id) }
117
+ end
118
+ end
119
+
120
+ context "for an array with :typecast option of Date" do
121
+ before { @key = Key.new(:dates, Array, :typecast => 'Date') }
122
+ subject { @key }
123
+
124
+ it "should cast each element correctly when get" do
125
+ dates = [Date.yesterday, Date.today, Date.tomorrow.to_s]
126
+ subject.get(dates).should == dates.map { |date| Date.from_marklogic(date) }
127
+ end
128
+
129
+ it "should cast each element correctly when set" do
130
+ dates = [Date.yesterday, Date.today, Date.tomorrow.to_s]
131
+ subject.set(dates).should == dates.map { |date| Date.to_marklogic(date) }
132
+ end
133
+ end
134
+
135
+ context "for a set with :typecast option" do
136
+ before { @key = Key.new(:user_ids, Set, :typecast => 'ObjectId') }
137
+ subject { @key }
138
+
139
+ it "should cast each element correctly" do
140
+ ids = [MarkLogic::ObjectId.new, MarkLogic::ObjectId.new, MarkLogic::ObjectId.new.to_s, MarkLogic::ObjectId.new.to_s]
141
+ subject.set(ids).should == ids.map { |id| ObjectId.to_marklogic(id) }
142
+ end
143
+ end
144
+
145
+ context "with the :attributes option" do
146
+ subject { @key }
147
+ before { @key = Key.new(:test, String, :accessors => accessor) }
148
+
149
+ context "with :read" do
150
+ let(:accessor) { :read }
151
+
152
+ it { expect( subject.read_accessor? ).to be_truthy }
153
+ it { expect( subject.write_accessor? ).to be_falsey }
154
+ it { expect( subject.predicate_accessor? ).to be_falsey }
155
+ end
156
+
157
+ context "with :write" do
158
+ let(:accessor) { :write }
159
+
160
+ it { expect( subject.read_accessor? ).to be_falsey }
161
+ it { expect( subject.write_accessor? ).to be_truthy }
162
+ it { expect( subject.predicate_accessor? ).to be_falsey }
163
+ end
164
+
165
+ context "with :predicate" do
166
+ let(:accessor) { :predicate }
167
+
168
+ it { expect( subject.read_accessor? ).to be_falsey }
169
+ it { expect( subject.write_accessor? ).to be_falsey }
170
+ it { expect( subject.predicate_accessor? ).to be_truthy }
171
+ end
172
+
173
+ context "with an array of options" do
174
+ let(:accessor) { [:read, :write] }
175
+
176
+ it { expect( subject.read_accessor? ).to be_truthy }
177
+ it { expect( subject.write_accessor? ).to be_truthy }
178
+ it { expect( subject.predicate_accessor? ).to be_falsey }
179
+ end
180
+ end
181
+
182
+ context "setting a value with a custom type" do
183
+ it "should correctly typecast" do
184
+ key = Key.new(:foo, FooType)
185
+ key.set("something").should == 'to_marklogic'
186
+ end
187
+
188
+ it "should correctly typecast if object of that type is given" do
189
+ key = Key.new(:foo, FooType)
190
+ key.set(FooType.new('something')).should == 'to_marklogic'
191
+ end
192
+ end
193
+
194
+ context "getting a value with a custom type" do
195
+ it "should use #from_marklogic to convert back to custom type" do
196
+ key = Key.new(:foo, FooType)
197
+ key.get('something').should == 'from_marklogic'
198
+ end
199
+ end
200
+
201
+ context "getting a value" do
202
+ it "should work with a type" do
203
+ key = Key.new(:foo, String)
204
+ key.get('bar').should == 'bar'
205
+ end
206
+
207
+ it "should work without type" do
208
+ key = Key.new(:foo)
209
+ key.get([1, '2']).should == [1, '2']
210
+ key.get(false).should == false
211
+ key.get({}).should == {}
212
+ end
213
+
214
+ context "for a embedded_document" do
215
+ it "should default to nil" do
216
+ key = Key.new(:foo, Address)
217
+ key.get(nil).should be_nil
218
+ end
219
+
220
+ it "should return instance if instance" do
221
+ address = Address.new(:city => 'South Bend', :state => 'IN', :zip => 46544)
222
+ key = Key.new(:foo, Address)
223
+ key.get(address).should == address
224
+ end
225
+ end
226
+ end
227
+
228
+ context "with a default set" do
229
+ before do
230
+ @key = Key.new(:foo, String, :default => 'baz')
231
+ end
232
+
233
+ context "#get" do
234
+ it "should return nil" do
235
+ @key.get(nil).should == nil
236
+ end
237
+
238
+ it "should return value if not blank" do
239
+ @key.get('foobar').should == 'foobar'
240
+ end
241
+
242
+ it "should return default value if name is _id and value nil" do
243
+ id = MarkLogic::ObjectId.new
244
+ key = Key.new(:_id, ObjectId, :default => lambda { id })
245
+ key.get(nil).should == id
246
+ end
247
+ end
248
+
249
+ context "#default_value" do
250
+ it "should return default value" do
251
+ @key.default_value.should == 'baz'
252
+ end
253
+
254
+ it "should return a dup of the default value" do
255
+ @key.default_value.replace('bar')
256
+ @key.default_value.should == 'baz'
257
+ end
258
+
259
+ it "should work with Boolean type and false value" do
260
+ Key.new(:active, Boolean, :default => false).default_value.should be_falsey
261
+ end
262
+
263
+ it "should work with Boolean type and true value" do
264
+ Key.new(:active, Boolean, :default => true).default_value.should be_truthy
265
+ end
266
+
267
+ it "should work with Array values" do
268
+ Key.new(:active, Array, :default => []).default_value.should == []
269
+ end
270
+
271
+ it "should work with procs" do
272
+ Key.new(:foo, String, :default => lambda { return 'hello world' }).default_value.should == "hello world"
273
+ end
274
+ end
275
+ end
276
+ end # KeyTest
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "Key" do
5
+ context ".new with no id and _id of type integer" do
6
+ it "should not error" do
7
+ lambda {
8
+ klass = Doc() do
9
+ key :_id, Integer
10
+ end
11
+ # No sensible default id for integer, people better pass them in if they user this
12
+ silence_stderr { klass.new.id.should be_nil }
13
+ }.should_not raise_error
14
+ end
15
+ end
16
+
17
+ context ".key?(:symbol)" do
18
+ it "should be true if document has key" do
19
+ Address.key?(:city).should be_truthy
20
+ end
21
+
22
+ it "should be false if document does not have key" do
23
+ Address.key?(:foo).should be_falsey
24
+ end
25
+ end
26
+
27
+ context "#assign" do
28
+ it "should raise a deprecation warning" do
29
+ klass = Doc() do
30
+ key :_id, Integer
31
+ end
32
+ doc = klass.new
33
+ expect(doc).to receive(:warn).once
34
+ doc.assign({:x => :y})
35
+ end
36
+ end
37
+
38
+ # TODO: Are these methods deprecated?
39
+ context "#embedded and #non_embedded_keys" do
40
+ EmbeddableThingie = EDoc {
41
+ key :whiz, String
42
+ }
43
+
44
+ let(:klass) do
45
+ Doc do
46
+ key :foo, String
47
+ key :embeddable_thingie, EmbeddableThingie
48
+ end
49
+ end
50
+
51
+ it "should get non-embeddable keys" do
52
+ klass.new.non_embedded_keys.map(&:name).should =~ %w(_id foo)
53
+ end
54
+
55
+ it "should get embeddable keys" do
56
+ klass.new.embedded_keys.map(&:name).should == %w(embeddable_thingie)
57
+ end
58
+ end
59
+
60
+ context ".key?('string')" do
61
+ it "should be true if document has key" do
62
+ Address.key?('city').should be_truthy
63
+ end
64
+
65
+ it "should be false if document does not have key" do
66
+ Address.key?('foo').should be_falsey
67
+ end
68
+ end
69
+
70
+ context ".new (from database)" do
71
+ before do
72
+ @klass = Doc do
73
+ key :user, Hash
74
+
75
+ def user=(user)
76
+ super(:id => user.id, :name => user.name)
77
+ end
78
+ end
79
+
80
+ user_class = Struct.new(:id, :name)
81
+ @klass.create(:user => user_class.new(1, 'John Nunemaker'))
82
+ end
83
+
84
+ it "should use []= for keys instead of public writer" do
85
+ expect {
86
+ doc = @klass.first
87
+ doc.user['id'].should == 1
88
+ doc.user['name'].should == 'John Nunemaker'
89
+ }.to_not raise_error
90
+ end
91
+ end
92
+
93
+ context ".load" do
94
+ it "should return nil if argument is nil" do
95
+ Doc().load(nil).should be_nil
96
+ end
97
+ end
98
+
99
+ context "default values" do
100
+ before do
101
+ @klass = Doc do
102
+ key :value, Integer, :default => 1
103
+ end
104
+ end
105
+
106
+ it "should initialize default value" do
107
+ @klass.new.value.should == 1
108
+ end
109
+
110
+ it "should allow overriding default value" do
111
+ @klass.new(:value => 2).value.should == 2
112
+ end
113
+
114
+ it "should allow re-setting a value that is defaulted" do
115
+ instance = @klass.new
116
+ instance.value = 2
117
+ instance.value.should == 2
118
+ instance.value = nil
119
+ instance.value.should == nil
120
+ end
121
+
122
+ context "for _id" do
123
+ before do
124
+ @klass.class_eval do
125
+ key :_id, Integer, :default => lambda { 12345 }
126
+ end
127
+ end
128
+
129
+ it "should work" do
130
+ @klass.new._id.should == 12345
131
+ end
132
+ end
133
+ end
134
+
135
+ context "when loading from the database" do
136
+ it "should not set default values for keys that already exist" do
137
+ counter = 0
138
+ instance = nil
139
+
140
+ klass = Doc do
141
+ key :value, Integer, :default => lambda { counter += 1 }
142
+ end
143
+
144
+ expect { instance = klass.create }.to change { counter }.by(1)
145
+ expect {
146
+ instance.reload.value.should == 1
147
+
148
+ instance.value = 10
149
+ instance.save
150
+
151
+ instance.reload.value.should == 10
152
+ }.to_not change { counter }
153
+ end
154
+ end
155
+ end # KeyTest