mongomodel 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 (108) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +34 -0
  3. data/Rakefile +47 -0
  4. data/bin/console +45 -0
  5. data/lib/mongomodel.rb +92 -0
  6. data/lib/mongomodel/attributes/mongo.rb +40 -0
  7. data/lib/mongomodel/attributes/store.rb +30 -0
  8. data/lib/mongomodel/attributes/typecasting.rb +51 -0
  9. data/lib/mongomodel/concerns/abstract_class.rb +17 -0
  10. data/lib/mongomodel/concerns/activemodel.rb +11 -0
  11. data/lib/mongomodel/concerns/associations.rb +103 -0
  12. data/lib/mongomodel/concerns/associations/base/association.rb +33 -0
  13. data/lib/mongomodel/concerns/associations/base/definition.rb +56 -0
  14. data/lib/mongomodel/concerns/associations/base/proxy.rb +58 -0
  15. data/lib/mongomodel/concerns/associations/belongs_to.rb +68 -0
  16. data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +159 -0
  17. data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +175 -0
  18. data/lib/mongomodel/concerns/attribute_methods.rb +55 -0
  19. data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +29 -0
  20. data/lib/mongomodel/concerns/attribute_methods/dirty.rb +35 -0
  21. data/lib/mongomodel/concerns/attribute_methods/protected.rb +127 -0
  22. data/lib/mongomodel/concerns/attribute_methods/query.rb +22 -0
  23. data/lib/mongomodel/concerns/attribute_methods/read.rb +29 -0
  24. data/lib/mongomodel/concerns/attribute_methods/write.rb +29 -0
  25. data/lib/mongomodel/concerns/attributes.rb +85 -0
  26. data/lib/mongomodel/concerns/callbacks.rb +294 -0
  27. data/lib/mongomodel/concerns/logging.rb +15 -0
  28. data/lib/mongomodel/concerns/pretty_inspect.rb +29 -0
  29. data/lib/mongomodel/concerns/properties.rb +69 -0
  30. data/lib/mongomodel/concerns/record_status.rb +42 -0
  31. data/lib/mongomodel/concerns/timestamps.rb +32 -0
  32. data/lib/mongomodel/concerns/validations.rb +38 -0
  33. data/lib/mongomodel/concerns/validations/associated.rb +46 -0
  34. data/lib/mongomodel/document.rb +20 -0
  35. data/lib/mongomodel/document/callbacks.rb +46 -0
  36. data/lib/mongomodel/document/dynamic_finders.rb +88 -0
  37. data/lib/mongomodel/document/finders.rb +82 -0
  38. data/lib/mongomodel/document/indexes.rb +91 -0
  39. data/lib/mongomodel/document/optimistic_locking.rb +48 -0
  40. data/lib/mongomodel/document/persistence.rb +143 -0
  41. data/lib/mongomodel/document/scopes.rb +161 -0
  42. data/lib/mongomodel/document/validations.rb +68 -0
  43. data/lib/mongomodel/document/validations/uniqueness.rb +78 -0
  44. data/lib/mongomodel/embedded_document.rb +42 -0
  45. data/lib/mongomodel/locale/en.yml +55 -0
  46. data/lib/mongomodel/support/collection.rb +109 -0
  47. data/lib/mongomodel/support/configuration.rb +35 -0
  48. data/lib/mongomodel/support/core_extensions.rb +10 -0
  49. data/lib/mongomodel/support/exceptions.rb +25 -0
  50. data/lib/mongomodel/support/mongo_options.rb +177 -0
  51. data/lib/mongomodel/support/types.rb +35 -0
  52. data/lib/mongomodel/support/types/array.rb +11 -0
  53. data/lib/mongomodel/support/types/boolean.rb +25 -0
  54. data/lib/mongomodel/support/types/custom.rb +38 -0
  55. data/lib/mongomodel/support/types/date.rb +20 -0
  56. data/lib/mongomodel/support/types/float.rb +13 -0
  57. data/lib/mongomodel/support/types/hash.rb +18 -0
  58. data/lib/mongomodel/support/types/integer.rb +13 -0
  59. data/lib/mongomodel/support/types/object.rb +21 -0
  60. data/lib/mongomodel/support/types/string.rb +9 -0
  61. data/lib/mongomodel/support/types/symbol.rb +9 -0
  62. data/lib/mongomodel/support/types/time.rb +12 -0
  63. data/lib/mongomodel/version.rb +3 -0
  64. data/spec/mongomodel/attributes/store_spec.rb +273 -0
  65. data/spec/mongomodel/concerns/activemodel_spec.rb +61 -0
  66. data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +153 -0
  67. data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +165 -0
  68. data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +192 -0
  69. data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +46 -0
  70. data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +131 -0
  71. data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +86 -0
  72. data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +27 -0
  73. data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +52 -0
  74. data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +43 -0
  75. data/spec/mongomodel/concerns/attributes_spec.rb +152 -0
  76. data/spec/mongomodel/concerns/callbacks_spec.rb +90 -0
  77. data/spec/mongomodel/concerns/logging_spec.rb +20 -0
  78. data/spec/mongomodel/concerns/pretty_inspect_spec.rb +68 -0
  79. data/spec/mongomodel/concerns/properties_spec.rb +29 -0
  80. data/spec/mongomodel/concerns/timestamps_spec.rb +170 -0
  81. data/spec/mongomodel/concerns/validations_spec.rb +159 -0
  82. data/spec/mongomodel/document/callbacks_spec.rb +80 -0
  83. data/spec/mongomodel/document/dynamic_finders_spec.rb +183 -0
  84. data/spec/mongomodel/document/finders_spec.rb +231 -0
  85. data/spec/mongomodel/document/indexes_spec.rb +121 -0
  86. data/spec/mongomodel/document/optimistic_locking_spec.rb +57 -0
  87. data/spec/mongomodel/document/persistence_spec.rb +319 -0
  88. data/spec/mongomodel/document/scopes_spec.rb +204 -0
  89. data/spec/mongomodel/document/validations/uniqueness_spec.rb +217 -0
  90. data/spec/mongomodel/document/validations_spec.rb +132 -0
  91. data/spec/mongomodel/document_spec.rb +74 -0
  92. data/spec/mongomodel/embedded_document_spec.rb +66 -0
  93. data/spec/mongomodel/mongomodel_spec.rb +33 -0
  94. data/spec/mongomodel/support/collection_spec.rb +248 -0
  95. data/spec/mongomodel/support/mongo_options_spec.rb +295 -0
  96. data/spec/mongomodel/support/property_spec.rb +83 -0
  97. data/spec/spec.opts +6 -0
  98. data/spec/spec_helper.rb +21 -0
  99. data/spec/specdoc.opts +6 -0
  100. data/spec/support/callbacks.rb +44 -0
  101. data/spec/support/helpers/define_class.rb +24 -0
  102. data/spec/support/helpers/specs_for.rb +11 -0
  103. data/spec/support/matchers/be_a_subclass_of.rb +5 -0
  104. data/spec/support/matchers/respond_to_boolean.rb +17 -0
  105. data/spec/support/matchers/run_callbacks.rb +20 -0
  106. data/spec/support/models.rb +23 -0
  107. data/spec/support/time.rb +6 -0
  108. metadata +232 -0
@@ -0,0 +1,35 @@
1
+ require 'mongomodel/support/types/object'
2
+ require 'mongomodel/support/types/string'
3
+ require 'mongomodel/support/types/integer'
4
+ require 'mongomodel/support/types/float'
5
+ require 'mongomodel/support/types/boolean'
6
+ require 'mongomodel/support/types/symbol'
7
+ require 'mongomodel/support/types/date'
8
+ require 'mongomodel/support/types/time'
9
+ require 'mongomodel/support/types/custom'
10
+ require 'mongomodel/support/types/array'
11
+ require 'mongomodel/support/types/hash'
12
+
13
+ module MongoModel
14
+ module Types
15
+ CONVERTERS = {
16
+ ::String => Types::String.new,
17
+ ::Integer => Types::Integer.new,
18
+ ::Float => Types::Float.new,
19
+ ::Boolean => Types::Boolean.new,
20
+ ::Symbol => Types::Symbol.new,
21
+ ::Date => Types::Date.new,
22
+ ::Time => Types::Time.new,
23
+ ::Array => Types::Array.new,
24
+ ::Hash => Types::Hash.new
25
+ }
26
+
27
+ def self.converter_for(type)
28
+ if CONVERTERS[type]
29
+ CONVERTERS[type]
30
+ else
31
+ CONVERTERS[type] = Types::Custom.new(type)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module MongoModel
2
+ module Types
3
+ class Array < Object
4
+ def to_mongo(array)
5
+ array.map { |i|
6
+ Types.converter_for(i.class).to_mongo(i)
7
+ }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ module MongoModel
2
+ module Types
3
+ class Boolean < Object
4
+ TRUE_VALUES = [ true, 'true', 't', 'TRUE', 'T', 'YES', 'y', '1', 1 ]
5
+ FALSE_VALUES = [ false, 'false', 'f', 'FALSE', 'F', 'NO', 'n', '0', 0 ]
6
+
7
+ def cast(value)
8
+ if true?(value)
9
+ true
10
+ elsif false?(value)
11
+ false
12
+ end
13
+ end
14
+
15
+ private
16
+ def true?(value)
17
+ TRUE_VALUES.include?(value)
18
+ end
19
+
20
+ def false?(value)
21
+ FALSE_VALUES.include?(value)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+
3
+ module MongoModel
4
+ module Types
5
+ class Custom < Object
6
+ def initialize(type)
7
+ @type = type
8
+ end
9
+
10
+ def cast(value)
11
+ if value.is_a?(@type)
12
+ value
13
+ elsif @type.respond_to?(:cast)
14
+ @type.cast(value)
15
+ else
16
+ @type.new(value)
17
+ end
18
+ end
19
+
20
+ def to_mongo(value)
21
+ if value.respond_to?(:to_mongo)
22
+ value.to_mongo
23
+ else
24
+ value
25
+ end
26
+ end
27
+
28
+ def from_mongo(value)
29
+ if @type.respond_to?(:from_mongo)
30
+ value = value.with_indifferent_access if value.respond_to?(:with_indifferent_access)
31
+ @type.from_mongo(value)
32
+ else
33
+ value
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ require 'active_support/core_ext/date/conversions'
2
+ require 'active_support/core_ext/string/conversions'
3
+
4
+ module MongoModel
5
+ module Types
6
+ class Date < Object
7
+ def cast(value)
8
+ value.to_date rescue nil
9
+ end
10
+
11
+ def to_mongo(value)
12
+ value.strftime("%Y/%m/%d") if value
13
+ end
14
+
15
+ def from_mongo(value)
16
+ value.to_date if value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module MongoModel
2
+ module Types
3
+ class Float < Object
4
+ def cast(value)
5
+ value.to_f if value.respond_to?(:to_f)
6
+ end
7
+
8
+ def boolean(value)
9
+ !value.zero?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+
3
+ module MongoModel
4
+ module Types
5
+ class Hash < Object
6
+ def to_mongo(hash)
7
+ hash.inject({}) { |result, (k, v)|
8
+ result[k] = Types.converter_for(v.class).to_mongo(v)
9
+ result
10
+ }
11
+ end
12
+
13
+ def from_mongo(hash)
14
+ hash.with_indifferent_access if hash
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module MongoModel
2
+ module Types
3
+ class Integer < Object
4
+ def cast(value)
5
+ value.to_i if value.respond_to?(:to_i)
6
+ end
7
+
8
+ def boolean(value)
9
+ !value.zero?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module MongoModel
2
+ module Types
3
+ class Object
4
+ def cast(value)
5
+ value
6
+ end
7
+
8
+ def boolean(value)
9
+ !value.blank?
10
+ end
11
+
12
+ def to_mongo(value)
13
+ value
14
+ end
15
+
16
+ def from_mongo(value)
17
+ value
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module MongoModel
2
+ module Types
3
+ class String < Object
4
+ def cast(value)
5
+ value.to_s if value.respond_to?(:to_s)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MongoModel
2
+ module Types
3
+ class Symbol < Object
4
+ def cast(value)
5
+ value.to_sym if value.respond_to?(:to_sym)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'active_support/core_ext/time/conversions'
2
+ require 'active_support/core_ext/string/conversions'
3
+
4
+ module MongoModel
5
+ module Types
6
+ class Time < Object
7
+ def cast(value)
8
+ value.to_time.utc rescue nil
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module MongoModel
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,273 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/hash/indifferent_access'
3
+
4
+ module MongoModel
5
+ describe Attributes::Store do
6
+ let(:properties) do
7
+ properties = ActiveSupport::OrderedHash.new
8
+ properties[:string] = MongoModel::Properties::Property.new(:string, String)
9
+ properties[:integer] = MongoModel::Properties::Property.new(:integer, Integer)
10
+ properties[:float] = MongoModel::Properties::Property.new(:float, Float)
11
+ properties[:boolean] = MongoModel::Properties::Property.new(:boolean, Boolean)
12
+ properties[:symbol] = MongoModel::Properties::Property.new(:symbol, Symbol)
13
+ properties[:hash] = MongoModel::Properties::Property.new(:hash, Hash)
14
+ properties[:array] = MongoModel::Properties::Property.new(:array, Array)
15
+ properties[:date] = MongoModel::Properties::Property.new(:date, Date)
16
+ properties[:time] = MongoModel::Properties::Property.new(:time, Time)
17
+ properties[:custom] = MongoModel::Properties::Property.new(:custom, CustomClass)
18
+ properties[:default] = MongoModel::Properties::Property.new(:default, String, :default => 'Default')
19
+ properties[:as] = MongoModel::Properties::Property.new(:as, String, :as => '_custom_as')
20
+ properties
21
+ end
22
+ let(:instance) { mock('instance', :properties => properties) }
23
+
24
+ subject { Attributes::Store.new(instance) }
25
+
26
+ it "should set default property values" do
27
+ subject.keys.should == properties.keys
28
+ subject[:default].should == 'Default'
29
+ end
30
+
31
+ describe "setting to nil" do
32
+ specify "all property types should be nullable" do
33
+ properties.keys.each do |property|
34
+ subject[property] = nil
35
+ subject[property].should be_nil
36
+ end
37
+ end
38
+ end
39
+
40
+ it "should set attributes that aren't properties" do
41
+ subject[:non_property] = "Hello World"
42
+ subject[:non_property].should == "Hello World"
43
+ end
44
+
45
+ describe "type-casting" do
46
+ TypeCastExamples = {
47
+ :string =>
48
+ {
49
+ "abc" => "abc",
50
+ 123 => "123"
51
+ },
52
+ :integer =>
53
+ {
54
+ 123 => 123,
55
+ 55.123 => 55,
56
+ "999" => 999,
57
+ "12.123" => 12
58
+ },
59
+ :float =>
60
+ {
61
+ 55.123 => 55.123,
62
+ 123 => 123.0,
63
+ "12.123" => 12.123
64
+ },
65
+ :boolean =>
66
+ {
67
+ true => true,
68
+ false => false,
69
+ "true" => true,
70
+ "false" => false,
71
+ 1 => true,
72
+ 0 => false,
73
+ "1" => true,
74
+ "0" => false,
75
+ '' => nil
76
+ },
77
+ :symbol =>
78
+ {
79
+ :some_symbol => :some_symbol,
80
+ "some_string" => :some_string
81
+ },
82
+ :hash =>
83
+ {
84
+ { :foo => 'bar' } => { :foo => 'bar' }
85
+ },
86
+ :array =>
87
+ {
88
+ [123, 'abc', :foo, true] => [123, 'abc', :foo, true]
89
+ },
90
+ :date =>
91
+ {
92
+ Date.civil(2009, 11, 15) => Date.civil(2009, 11, 15),
93
+ Time.local(2008, 12, 3, 0, 0, 0, 0) => Date.civil(2008, 12, 3),
94
+ "2009/3/4" => Date.civil(2009, 3, 4),
95
+ "Sat Jan 01 20:15:01 UTC 2000" => Date.civil(2000, 1, 1)
96
+ },
97
+ :time =>
98
+ {
99
+ Time.local(2008, 5, 14, 1, 2, 3, 4) => Time.local(2008, 5, 14, 1, 2, 3, 4),
100
+ Date.civil(2009, 11, 15) => Time.local(2009, 11, 15, 0, 0, 0, 0),
101
+ "Sat Jan 01 20:15:01 UTC 2000" => Time.utc(2000, 1, 1, 20, 15, 1, 0),
102
+ "2009/3/4" => Time.utc(2009, 3, 4, 0, 0, 0, 0)
103
+ }
104
+ }
105
+
106
+ TypeCastExamples.each do |type, examples|
107
+ context "assigning to #{type} property" do
108
+ examples.each do |assigned, expected|
109
+ it "should cast #{assigned.inspect} to #{expected.inspect}" do
110
+ subject[type] = assigned
111
+ subject[type].should == expected
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ context "assigning to custom property" do
118
+ before(:each) do
119
+ @custom = CustomClass.new('instance name')
120
+ end
121
+
122
+ it "should not alter instances of CustomClass" do
123
+ subject[:custom] = @custom
124
+ subject[:custom].should == @custom
125
+ end
126
+
127
+ it "should cast strings to CustomClass" do
128
+ subject[:custom] = "foobar"
129
+ subject[:custom].should == CustomClass.new('foobar')
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "#before_type_cast" do
135
+ BeforeTypeCastExamples = {
136
+ :string => [ "abc", 123 ],
137
+ :integer => [ 123, 55.123, "999", "12.123" ],
138
+ :float => [ 55.123, 123, "12.123" ],
139
+ :boolean => [ true, false, "true", "false", 1, 0, "1", "0", '' ],
140
+ :symbol => [ :some_symbol, "some_string" ],
141
+ :hash => [ { :foo => 'bar' } ],
142
+ :array => [ [123, 'abc', :foo, true] ],
143
+ :date => [ Date.civil(2009, 11, 15), Time.local(2008, 12, 3, 0, 0, 0, 0), "2009/3/4", "Sat Jan 01 20:15:01 UTC 2000" ],
144
+ :time => [ Time.local(2008, 5, 14, 1, 2, 3, 4), Date.civil(2009, 11, 15), "Sat Jan 01 20:15:01 UTC 2000", "2009/3/4" ]
145
+ }
146
+
147
+ BeforeTypeCastExamples.each do |type, examples|
148
+ context "assigning to #{type} property" do
149
+ examples.each do |example|
150
+ it "should access pre-typecasted value of #{example.inspect}" do
151
+ subject[type] = example
152
+ subject.before_type_cast(type).should == example
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ describe "#has?" do
160
+ TrueExamples = {
161
+ :string => [ 'abc', '1' ],
162
+ :integer => [ -1, 1, 100 ],
163
+ :float => [ 0.1, 44.123 ],
164
+ :boolean => [ true, 1, "true" ],
165
+ :symbol => [ :some_symbol ],
166
+ :hash => [ { :foo => 'bar' } ],
167
+ :array => [ [''], [123, 'abc', :foo, true] ],
168
+ :date => [ Date.civil(2009, 11, 15) ],
169
+ :time => [ Time.local(2008, 5, 14, 1, 2, 3, 4) ],
170
+ :custom => [ CustomClass.new('foobar'), 'baz' ]
171
+ }
172
+
173
+ FalseExamples = {
174
+ :string => [ nil, '' ],
175
+ :integer => [ nil, 0 ],
176
+ :float => [ nil, 0.0 ],
177
+ :boolean => [ nil, false, 0, "false" ],
178
+ :symbol => [ nil, 0 ],
179
+ :hash => [ nil, {} ],
180
+ :array => [ [] ],
181
+ :date => [ nil, '' ],
182
+ :time => [ nil, '' ],
183
+ :custom => [ nil ]
184
+ }
185
+
186
+ TrueExamples.each do |type, examples|
187
+ context "assigning to #{type} property" do
188
+ examples.each do |example|
189
+ it "should return true for #{example.inspect}" do
190
+ subject[type] = example
191
+ subject.has?(type).should == true
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ FalseExamples.each do |type, examples|
198
+ context "assigning to #{type} property" do
199
+ examples.each do |example|
200
+ it "should return false for #{example.inspect}" do
201
+ subject[type] = example
202
+ subject.has?(type).should == false
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ describe "serialization" do
210
+ it "should convert to mongo representation" do
211
+ subject[:string] = 'string'
212
+ subject[:integer] = 42
213
+ subject[:float] = 123.45
214
+ subject[:boolean] = false
215
+ subject[:symbol] = :symbol
216
+ subject[:hash] = { :foo => 'bar', :custom => CustomClass.new('custom in hash') }
217
+ subject[:array] = [ 123, 'abc', 45.67, true, :bar, CustomClass.new('custom in array') ]
218
+ subject[:date] = Date.civil(2009, 11, 15)
219
+ subject[:time] = Time.local(2008, 5, 14, 1, 2, 3, 4)
220
+ subject[:custom] = CustomClass.new('custom')
221
+ subject[:as] = "As property"
222
+ subject[:non_property] = "Hello World"
223
+ subject[:custom_non_property] = CustomClass.new('custom non property')
224
+
225
+ subject.to_mongo.should include({
226
+ 'string' => 'string',
227
+ 'integer' => 42,
228
+ 'float' => 123.45,
229
+ 'boolean' => false,
230
+ 'symbol' => :symbol,
231
+ 'hash' => { :foo => 'bar', :custom => { :name => 'custom in hash' } },
232
+ 'array' => [ 123, 'abc', 45.67, true, :bar, { :name => 'custom in array' } ],
233
+ 'date' => "2009/11/15",
234
+ 'time' => Time.local(2008, 5, 14, 1, 2, 3, 4),
235
+ 'custom' => { :name => 'custom' },
236
+ '_custom_as' => "As property",
237
+ 'non_property' => "Hello World",
238
+ 'custom_non_property' => { :name => 'custom non property' },
239
+ })
240
+ end
241
+
242
+ it "should load from mongo representation" do
243
+ subject.from_mongo!({
244
+ 'string' => 'string',
245
+ 'integer' => 42,
246
+ 'float' => 123.45,
247
+ 'boolean' => false,
248
+ 'symbol' => :symbol,
249
+ 'hash' => { :foo => 'bar' },
250
+ 'array' => [ 123, 'abc', 45.67, true, :bar ],
251
+ 'date' => Time.utc(2009, 11, 15),
252
+ 'time' => Time.local(2008, 5, 14, 1, 2, 3, 4),
253
+ 'custom' => { :name => 'custom' },
254
+ '_custom_as' => "As property",
255
+ 'custom_non_property' => { :name => 'custom non property' }
256
+ })
257
+
258
+ subject[:string].should == 'string'
259
+ subject[:integer].should == 42
260
+ subject[:float].should == 123.45
261
+ subject[:boolean].should == false
262
+ subject[:symbol].should == :symbol
263
+ subject[:hash].should == { :foo => 'bar' }.with_indifferent_access
264
+ subject[:array].should == [ 123, 'abc', 45.67, true, :bar ]
265
+ subject[:date].should == Date.civil(2009, 11, 15)
266
+ subject[:time].should == Time.local(2008, 5, 14, 1, 2, 3, 4)
267
+ subject[:custom].should == CustomClass.new('custom')
268
+ subject[:as].should == "As property"
269
+ subject[:custom_non_property].should == { :name => 'custom non property' }
270
+ end
271
+ end
272
+ end
273
+ end