pwnash-mongo_mapper 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongo_mapper.rb +6 -8
- data/lib/mongo_mapper/document.rb +6 -281
- data/lib/mongo_mapper/embedded_document.rb +5 -45
- data/lib/mongo_mapper/extensions.rb +190 -0
- data/lib/mongo_mapper/plugins.rb +27 -18
- data/lib/mongo_mapper/plugins/associations.rb +7 -6
- data/lib/mongo_mapper/plugins/associations/base.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +2 -1
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +4 -4
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +4 -3
- data/lib/mongo_mapper/plugins/clone.rb +1 -0
- data/lib/mongo_mapper/plugins/descendants.rb +1 -0
- data/lib/mongo_mapper/plugins/dirty.rb +1 -0
- data/lib/mongo_mapper/plugins/document.rb +40 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +42 -0
- data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +2 -36
- data/lib/mongo_mapper/plugins/embedded_document.rb +48 -0
- data/lib/mongo_mapper/plugins/equality.rb +1 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +8 -11
- data/lib/mongo_mapper/plugins/indexes.rb +11 -0
- data/lib/mongo_mapper/plugins/inspect.rb +1 -0
- data/lib/mongo_mapper/plugins/keys.rb +7 -9
- data/lib/mongo_mapper/plugins/keys/key.rb +12 -2
- data/lib/mongo_mapper/plugins/logger.rb +1 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +3 -2
- data/lib/mongo_mapper/plugins/pagination.rb +1 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/persistence.rb +1 -0
- data/lib/mongo_mapper/plugins/protected.rb +1 -0
- data/lib/mongo_mapper/plugins/query_logger.rb +5 -10
- data/lib/mongo_mapper/plugins/querying.rb +236 -0
- data/lib/mongo_mapper/plugins/rails.rb +1 -0
- data/lib/mongo_mapper/plugins/sci.rb +31 -0
- data/lib/mongo_mapper/plugins/serialization.rb +1 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
- data/lib/mongo_mapper/plugins/validations.rb +5 -1
- data/lib/mongo_mapper/query.rb +53 -120
- data/lib/mongo_mapper/support.rb +2 -213
- data/lib/mongo_mapper/support/descendant_appends.rb +3 -6
- data/lib/mongo_mapper/version.rb +2 -1
- metadata +156 -190
- data/.gitignore +0 -10
- data/Rakefile +0 -37
- data/mongo_mapper.gemspec +0 -216
- data/performance/read_write.rb +0 -52
- data/specs.watchr +0 -51
- data/test/NOTE_ON_TESTING +0 -1
- data/test/active_model_lint_test.rb +0 -13
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +0 -63
- data/test/functional/associations/test_belongs_to_proxy.rb +0 -101
- data/test/functional/associations/test_in_array_proxy.rb +0 -325
- data/test/functional/associations/test_many_documents_as_proxy.rb +0 -229
- data/test/functional/associations/test_many_documents_proxy.rb +0 -536
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +0 -176
- data/test/functional/associations/test_many_embedded_proxy.rb +0 -256
- data/test/functional/associations/test_many_polymorphic_proxy.rb +0 -302
- data/test/functional/associations/test_one_embedded_proxy.rb +0 -68
- data/test/functional/associations/test_one_proxy.rb +0 -196
- data/test/functional/test_associations.rb +0 -44
- data/test/functional/test_binary.rb +0 -27
- data/test/functional/test_callbacks.rb +0 -151
- data/test/functional/test_dirty.rb +0 -163
- data/test/functional/test_document.rb +0 -1219
- data/test/functional/test_embedded_document.rb +0 -210
- data/test/functional/test_identity_map.rb +0 -507
- data/test/functional/test_indexing.rb +0 -44
- data/test/functional/test_logger.rb +0 -20
- data/test/functional/test_modifiers.rb +0 -416
- data/test/functional/test_pagination.rb +0 -93
- data/test/functional/test_protected.rb +0 -163
- data/test/functional/test_string_id_compatibility.rb +0 -67
- data/test/functional/test_timestamps.rb +0 -64
- data/test/functional/test_userstamps.rb +0 -28
- data/test/functional/test_validations.rb +0 -342
- data/test/models.rb +0 -227
- data/test/support/custom_matchers.rb +0 -37
- data/test/support/timing.rb +0 -16
- data/test/test_helper.rb +0 -64
- data/test/unit/associations/test_base.rb +0 -212
- data/test/unit/associations/test_proxy.rb +0 -105
- data/test/unit/serializers/test_json_serializer.rb +0 -202
- data/test/unit/test_descendant_appends.rb +0 -71
- data/test/unit/test_document.rb +0 -225
- data/test/unit/test_dynamic_finder.rb +0 -123
- data/test/unit/test_embedded_document.rb +0 -657
- data/test/unit/test_keys.rb +0 -216
- data/test/unit/test_mongo_mapper.rb +0 -118
- data/test/unit/test_pagination.rb +0 -160
- data/test/unit/test_plugins.rb +0 -50
- data/test/unit/test_query.rb +0 -374
- data/test/unit/test_rails.rb +0 -181
- data/test/unit/test_rails_compatibility.rb +0 -52
- data/test/unit/test_serialization.rb +0 -51
- data/test/unit/test_support.rb +0 -390
- data/test/unit/test_time_zones.rb +0 -39
- data/test/unit/test_validations.rb +0 -544
data/lib/mongo_mapper.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# gem 'mongo', '1.0'
|
4
|
-
# gem 'jnunemaker-validatable', '1.8.4'
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Make sure you have the correct versions of the gems (see gemspec) in your load path.
|
5
3
|
require 'set'
|
6
4
|
require 'uri'
|
7
|
-
require '
|
5
|
+
require 'plucky'
|
8
6
|
require 'validatable'
|
9
7
|
require 'active_support/all'
|
10
8
|
|
@@ -92,8 +90,7 @@ module MongoMapper
|
|
92
90
|
end
|
93
91
|
|
94
92
|
def self.setup(config, environment, options={})
|
95
|
-
|
96
|
-
handle_passenger_forking if using_passenger
|
93
|
+
handle_passenger_forking
|
97
94
|
self.config = config
|
98
95
|
connect(environment, options)
|
99
96
|
end
|
@@ -106,11 +103,12 @@ module MongoMapper
|
|
106
103
|
end
|
107
104
|
end
|
108
105
|
|
109
|
-
autoload :Query, 'mongo_mapper/query'
|
110
106
|
autoload :Document, 'mongo_mapper/document'
|
111
107
|
autoload :EmbeddedDocument, 'mongo_mapper/embedded_document'
|
108
|
+
autoload :Query, 'mongo_mapper/query'
|
112
109
|
autoload :Version, 'mongo_mapper/version'
|
113
110
|
end
|
114
111
|
|
112
|
+
require 'mongo_mapper/extensions'
|
115
113
|
require 'mongo_mapper/support'
|
116
114
|
require 'mongo_mapper/plugins'
|
@@ -1,19 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module Document
|
3
4
|
extend Support::DescendantAppends
|
4
5
|
|
5
6
|
def self.included(model)
|
6
7
|
model.class_eval do
|
7
|
-
include InstanceMethods
|
8
|
-
extend Support::Find
|
9
|
-
extend ClassMethods
|
10
8
|
extend Plugins
|
11
9
|
|
10
|
+
plugin Plugins::Document
|
11
|
+
plugin Plugins::Querying # for now needs to be before associations (save_to_collection)
|
12
12
|
plugin Plugins::Associations
|
13
13
|
plugin Plugins::Clone
|
14
14
|
plugin Plugins::Descendants
|
15
|
+
plugin Plugins::DynamicQuerying
|
15
16
|
plugin Plugins::Equality
|
16
17
|
plugin Plugins::Inspect
|
18
|
+
plugin Plugins::Indexes
|
17
19
|
plugin Plugins::Keys
|
18
20
|
plugin Plugins::Dirty # for now dirty needs to be after keys
|
19
21
|
plugin Plugins::Logger
|
@@ -22,6 +24,7 @@ module MongoMapper
|
|
22
24
|
plugin Plugins::Persistence
|
23
25
|
plugin Plugins::Protected
|
24
26
|
plugin Plugins::Rails
|
27
|
+
plugin Plugins::Sci
|
25
28
|
plugin Plugins::Serialization
|
26
29
|
plugin Plugins::Timestamps
|
27
30
|
plugin Plugins::Userstamps
|
@@ -29,286 +32,8 @@ module MongoMapper
|
|
29
32
|
plugin Plugins::Callbacks # for now callbacks needs to be after validations
|
30
33
|
plugin Plugins::QueryLogger
|
31
34
|
|
32
|
-
extend Plugins::Validations::DocumentMacros
|
33
35
|
end
|
34
|
-
|
35
36
|
super
|
36
37
|
end
|
37
|
-
|
38
|
-
module ClassMethods
|
39
|
-
def inherited(subclass)
|
40
|
-
subclass.set_collection_name(collection_name)
|
41
|
-
super
|
42
|
-
end
|
43
|
-
|
44
|
-
def ensure_index(spec, options={})
|
45
|
-
collection.create_index(spec, options)
|
46
|
-
end
|
47
|
-
|
48
|
-
def find(*args)
|
49
|
-
assert_no_first_last_or_all(args)
|
50
|
-
options = args.extract_options!
|
51
|
-
return nil if args.size == 0
|
52
|
-
|
53
|
-
if args.first.is_a?(Array) || args.size > 1
|
54
|
-
find_some(args, options)
|
55
|
-
else
|
56
|
-
find_one(options.merge({:_id => args[0]}))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def find!(*args)
|
61
|
-
assert_no_first_last_or_all(args)
|
62
|
-
options = args.extract_options!
|
63
|
-
raise DocumentNotFound, "Couldn't find without an ID" if args.size == 0
|
64
|
-
|
65
|
-
if args.first.is_a?(Array) || args.size > 1
|
66
|
-
find_some!(args, options)
|
67
|
-
else
|
68
|
-
find_one(options.merge({:_id => args[0]})) || raise(DocumentNotFound, "Document match #{options.inspect} does not exist in #{collection.name} collection")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def find_each(options={})
|
73
|
-
criteria, options = to_query(options)
|
74
|
-
collection.find(criteria, options).each do |doc|
|
75
|
-
yield load(doc)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def find_by_id(id)
|
80
|
-
find(id)
|
81
|
-
end
|
82
|
-
|
83
|
-
def first_or_create(args)
|
84
|
-
first(args) || create(args.reject { |key, value| !key?(key) })
|
85
|
-
end
|
86
|
-
|
87
|
-
def first_or_new(args)
|
88
|
-
first(args) || new(args.reject { |key, value| !key?(key) })
|
89
|
-
end
|
90
|
-
|
91
|
-
def first(options={})
|
92
|
-
find_one(options)
|
93
|
-
end
|
94
|
-
|
95
|
-
def last(options={})
|
96
|
-
raise ':order option must be provided when using last' if options[:order].blank?
|
97
|
-
find_one(options.merge(:order => invert_order_clause(options[:order])))
|
98
|
-
end
|
99
|
-
|
100
|
-
def all(options={})
|
101
|
-
find_many(options)
|
102
|
-
end
|
103
|
-
|
104
|
-
def count(options={})
|
105
|
-
collection.find(to_criteria(options)).count
|
106
|
-
end
|
107
|
-
|
108
|
-
def exists?(options={})
|
109
|
-
!count(options).zero?
|
110
|
-
end
|
111
|
-
|
112
|
-
def create(*docs)
|
113
|
-
initialize_each(*docs) { |doc| doc.save }
|
114
|
-
end
|
115
|
-
|
116
|
-
def create!(*docs)
|
117
|
-
initialize_each(*docs) { |doc| doc.save! }
|
118
|
-
end
|
119
|
-
|
120
|
-
def update(*args)
|
121
|
-
if args.length == 1
|
122
|
-
update_multiple(args[0])
|
123
|
-
else
|
124
|
-
id, attributes = args
|
125
|
-
update_single(id, attributes)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def delete(*ids)
|
130
|
-
collection.remove(to_criteria(:_id => ids.flatten))
|
131
|
-
end
|
132
|
-
|
133
|
-
def delete_all(options={})
|
134
|
-
collection.remove(to_criteria(options))
|
135
|
-
end
|
136
|
-
|
137
|
-
def destroy(*ids)
|
138
|
-
find_some!(ids.flatten).each(&:destroy)
|
139
|
-
end
|
140
|
-
|
141
|
-
def destroy_all(options={})
|
142
|
-
find_each(options) { |document| document.destroy }
|
143
|
-
end
|
144
|
-
|
145
|
-
def embeddable?
|
146
|
-
false
|
147
|
-
end
|
148
|
-
|
149
|
-
def single_collection_inherited?
|
150
|
-
keys.key?(:_type) && single_collection_inherited_superclass?
|
151
|
-
end
|
152
|
-
|
153
|
-
def single_collection_inherited_superclass?
|
154
|
-
superclass.respond_to?(:keys) && superclass.keys.key?(:_type)
|
155
|
-
end
|
156
|
-
|
157
|
-
private
|
158
|
-
def initialize_each(*docs)
|
159
|
-
instances = []
|
160
|
-
docs = [{}] if docs.blank?
|
161
|
-
docs.flatten.each do |attrs|
|
162
|
-
doc = new(attrs)
|
163
|
-
yield(doc)
|
164
|
-
instances << doc
|
165
|
-
end
|
166
|
-
instances.size == 1 ? instances[0] : instances
|
167
|
-
end
|
168
|
-
|
169
|
-
def assert_no_first_last_or_all(args)
|
170
|
-
if args[0] == :first || args[0] == :last || args[0] == :all
|
171
|
-
raise ArgumentError, "#{self}.find(:#{args}) is no longer supported, use #{self}.#{args} instead."
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def find_some(ids, options={})
|
176
|
-
ids = ids.flatten.compact.uniq
|
177
|
-
find_many(options.merge(:_id => ids)).compact
|
178
|
-
end
|
179
|
-
|
180
|
-
def find_some!(ids, options={})
|
181
|
-
ids = ids.flatten.compact.uniq
|
182
|
-
documents = find_some(ids, options)
|
183
|
-
|
184
|
-
if ids.size == documents.size
|
185
|
-
documents
|
186
|
-
else
|
187
|
-
raise DocumentNotFound, "Couldn't find all of the ids (#{ids.to_sentence}). Found #{documents.size}, but was expecting #{ids.size}"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# All query methods that load documents pass through find_one or find_many
|
192
|
-
def find_one(options={})
|
193
|
-
criteria, options = to_query(options)
|
194
|
-
if doc = collection.find_one(criteria, options)
|
195
|
-
load(doc)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
# All query methods that load documents pass through find_one or find_many
|
200
|
-
def find_many(options)
|
201
|
-
criteria, options = to_query(options)
|
202
|
-
collection.find(criteria, options).to_a.map do |doc|
|
203
|
-
load(doc)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def invert_order_clause(order)
|
208
|
-
order.split(',').map do |order_segment|
|
209
|
-
if order_segment =~ /\sasc/i
|
210
|
-
order_segment.sub /\sasc/i, ' desc'
|
211
|
-
elsif order_segment =~ /\sdesc/i
|
212
|
-
order_segment.sub /\sdesc/i, ' asc'
|
213
|
-
else
|
214
|
-
"#{order_segment.strip} desc"
|
215
|
-
end
|
216
|
-
end.join(',')
|
217
|
-
end
|
218
|
-
|
219
|
-
def update_single(id, attrs)
|
220
|
-
if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
|
221
|
-
raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
|
222
|
-
end
|
223
|
-
|
224
|
-
doc = find(id)
|
225
|
-
doc.update_attributes(attrs)
|
226
|
-
doc
|
227
|
-
end
|
228
|
-
|
229
|
-
def update_multiple(docs)
|
230
|
-
unless docs.is_a?(Hash)
|
231
|
-
raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
|
232
|
-
end
|
233
|
-
|
234
|
-
instances = []
|
235
|
-
docs.each_pair { |id, attrs| instances << update(id, attrs) }
|
236
|
-
instances
|
237
|
-
end
|
238
|
-
|
239
|
-
def to_criteria(options={})
|
240
|
-
Query.new(self, options).criteria
|
241
|
-
end
|
242
|
-
|
243
|
-
def to_query(options={})
|
244
|
-
Query.new(self, options).to_a
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
module InstanceMethods
|
249
|
-
def save(options={})
|
250
|
-
options.assert_valid_keys(:validate, :safe)
|
251
|
-
options.reverse_merge!(:validate => true)
|
252
|
-
!options[:validate] || valid? ? create_or_update(options) : false
|
253
|
-
end
|
254
|
-
|
255
|
-
def save!(options={})
|
256
|
-
options.assert_valid_keys(:safe)
|
257
|
-
save(options) || raise(DocumentNotValid.new(self))
|
258
|
-
end
|
259
|
-
|
260
|
-
def destroy
|
261
|
-
delete
|
262
|
-
end
|
263
|
-
|
264
|
-
def delete
|
265
|
-
@_destroyed = true
|
266
|
-
self.class.delete(id) unless new?
|
267
|
-
end
|
268
|
-
|
269
|
-
def new?
|
270
|
-
@new
|
271
|
-
end
|
272
|
-
|
273
|
-
def destroyed?
|
274
|
-
@_destroyed == true
|
275
|
-
end
|
276
|
-
|
277
|
-
def reload
|
278
|
-
if attrs = collection.find_one({:_id => _id})
|
279
|
-
self.class.associations.each { |name, assoc| send(name).reset if respond_to?(name) }
|
280
|
-
self.attributes = attrs
|
281
|
-
self
|
282
|
-
else
|
283
|
-
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
# Used by embedded docs to find root easily without if/respond_to? stuff.
|
288
|
-
# Documents are always root documents.
|
289
|
-
def _root_document
|
290
|
-
self
|
291
|
-
end
|
292
|
-
|
293
|
-
private
|
294
|
-
def create_or_update(options={})
|
295
|
-
result = new? ? create(options) : update(options)
|
296
|
-
result != false
|
297
|
-
end
|
298
|
-
|
299
|
-
def create(options={})
|
300
|
-
save_to_collection(options)
|
301
|
-
end
|
302
|
-
|
303
|
-
def update(options={})
|
304
|
-
save_to_collection(options)
|
305
|
-
end
|
306
|
-
|
307
|
-
def save_to_collection(options={})
|
308
|
-
safe = options[:safe] || false
|
309
|
-
@new = false
|
310
|
-
collection.save(to_mongo, :safe => safe)
|
311
|
-
end
|
312
|
-
end
|
313
38
|
end # Document
|
314
39
|
end # MongoMapper
|
@@ -1,13 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module EmbeddedDocument
|
3
4
|
extend Support::DescendantAppends
|
4
5
|
|
5
6
|
def self.included(model)
|
6
7
|
model.class_eval do
|
7
|
-
include InstanceMethods
|
8
|
-
extend ClassMethods
|
9
8
|
extend Plugins
|
10
9
|
|
10
|
+
plugin Plugins::EmbeddedDocument
|
11
11
|
plugin Plugins::Associations
|
12
12
|
plugin Plugins::Clone
|
13
13
|
plugin Plugins::Descendants
|
@@ -18,54 +18,14 @@ module MongoMapper
|
|
18
18
|
plugin Plugins::Persistence
|
19
19
|
plugin Plugins::Protected
|
20
20
|
plugin Plugins::Rails
|
21
|
+
plugin Plugins::Sci
|
21
22
|
plugin Plugins::Serialization
|
22
23
|
plugin Plugins::Validations
|
23
24
|
plugin Plugins::Callbacks
|
24
25
|
plugin Plugins::QueryLogger
|
25
26
|
|
26
|
-
attr_reader :_root_document, :_parent_document
|
27
27
|
end
|
28
|
-
|
29
28
|
super
|
30
29
|
end
|
31
|
-
|
32
|
-
|
33
|
-
def embeddable?
|
34
|
-
true
|
35
|
-
end
|
36
|
-
|
37
|
-
def embedded_in(owner_name)
|
38
|
-
define_method(owner_name) { _parent_document }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
module InstanceMethods
|
43
|
-
def destroyed?
|
44
|
-
!!_root_document.try(:destroyed?)
|
45
|
-
end
|
46
|
-
|
47
|
-
def new?
|
48
|
-
_root_document.try(:new?) || @new
|
49
|
-
end
|
50
|
-
|
51
|
-
def save(options={})
|
52
|
-
if result = _root_document.try(:save, options)
|
53
|
-
@new = false
|
54
|
-
end
|
55
|
-
result
|
56
|
-
end
|
57
|
-
|
58
|
-
def save!(options={})
|
59
|
-
if result = _root_document.try(:save!, options)
|
60
|
-
@new = false
|
61
|
-
end
|
62
|
-
result
|
63
|
-
end
|
64
|
-
|
65
|
-
def _parent_document=(value)
|
66
|
-
@_root_document = value._root_document
|
67
|
-
@_parent_document = value
|
68
|
-
end
|
69
|
-
end # InstanceMethods
|
70
|
-
end # EmbeddedDocument
|
71
|
-
end # MongoMapper
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
class Array
|
3
|
+
def self.to_mongo(value)
|
4
|
+
value = value.respond_to?(:lines) ? value.lines : value
|
5
|
+
value.to_a
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.from_mongo(value)
|
9
|
+
value || []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Binary
|
14
|
+
def self.to_mongo(value)
|
15
|
+
if value.is_a?(BSON::Binary)
|
16
|
+
value
|
17
|
+
else
|
18
|
+
value.nil? ? nil : BSON::Binary.new(value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_mongo(value)
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Boolean
|
28
|
+
BOOLEAN_MAPPING = {
|
29
|
+
true => true, 'true' => true, 'TRUE' => true, 'True' => true, 't' => true, 'T' => true, '1' => true, 1 => true, 1.0 => true,
|
30
|
+
false => false, 'false' => false, 'FALSE' => false, 'False' => false, 'f' => false, 'F' => false, '0' => false, 0 => false, 0.0 => false, nil => nil
|
31
|
+
}
|
32
|
+
|
33
|
+
def self.to_mongo(value)
|
34
|
+
if value.is_a?(Boolean)
|
35
|
+
value
|
36
|
+
else
|
37
|
+
BOOLEAN_MAPPING[value]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_mongo(value)
|
42
|
+
!!value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Date
|
47
|
+
def self.to_mongo(value)
|
48
|
+
if value.nil? || value == ''
|
49
|
+
nil
|
50
|
+
else
|
51
|
+
date = value.is_a?(Date) || value.is_a?(Time) ? value : Date.parse(value.to_s)
|
52
|
+
Time.utc(date.year, date.month, date.day)
|
53
|
+
end
|
54
|
+
rescue
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.from_mongo(value)
|
59
|
+
value.to_date if value.present?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Float
|
64
|
+
def self.to_mongo(value)
|
65
|
+
value.nil? ? nil : value.to_f
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Hash
|
70
|
+
def self.from_mongo(value)
|
71
|
+
HashWithIndifferentAccess.new(value || {})
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_mongo
|
75
|
+
self
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Integer
|
80
|
+
def self.to_mongo(value)
|
81
|
+
value_to_i = value.to_i
|
82
|
+
if value_to_i == 0 && value != value_to_i
|
83
|
+
value.to_s =~ /^(0x|0b)?0+/ ? 0 : nil
|
84
|
+
else
|
85
|
+
value_to_i
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class NilClass
|
91
|
+
def to_mongo(value)
|
92
|
+
value
|
93
|
+
end
|
94
|
+
|
95
|
+
def from_mongo(value)
|
96
|
+
value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Object
|
101
|
+
# The hidden singleton lurks behind everyone
|
102
|
+
def metaclass
|
103
|
+
class << self; self end
|
104
|
+
end
|
105
|
+
|
106
|
+
def meta_eval(&blk)
|
107
|
+
metaclass.instance_eval(&blk)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Adds methods to a metaclass
|
111
|
+
def meta_def(name, &blk)
|
112
|
+
meta_eval { define_method(name, &blk) }
|
113
|
+
end
|
114
|
+
|
115
|
+
# Defines an instance method within a class
|
116
|
+
def class_def(name, &blk)
|
117
|
+
class_eval { define_method(name, &blk) }
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.to_mongo(value)
|
121
|
+
value
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.from_mongo(value)
|
125
|
+
value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class ObjectId
|
130
|
+
def self.to_mongo(value)
|
131
|
+
Plucky.to_object_id(value)
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.from_mongo(value)
|
135
|
+
value
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class Set
|
140
|
+
def self.to_mongo(value)
|
141
|
+
value.to_a
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.from_mongo(value)
|
145
|
+
Set.new(value || [])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class String
|
150
|
+
def self.to_mongo(value)
|
151
|
+
value.nil? ? nil : value.to_s
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.from_mongo(value)
|
155
|
+
value.nil? ? nil : value.to_s
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class Time
|
160
|
+
def self.to_mongo(value)
|
161
|
+
if value.nil? || value == ''
|
162
|
+
nil
|
163
|
+
else
|
164
|
+
time_class = Time.try(:zone).present? ? Time.zone : Time
|
165
|
+
time = value.is_a?(Time) ? value : time_class.parse(value.to_s)
|
166
|
+
# strip milliseconds as Ruby does micro and bson does milli and rounding rounded wrong
|
167
|
+
at(time.to_i).utc if time
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.from_mongo(value)
|
172
|
+
if Time.try(:zone).present? && value.present?
|
173
|
+
value.in_time_zone(Time.zone)
|
174
|
+
else
|
175
|
+
value
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class BSON::ObjectID
|
181
|
+
alias_method :original_to_json, :to_json
|
182
|
+
|
183
|
+
def as_json(options=nil)
|
184
|
+
to_s
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_json(options = nil)
|
188
|
+
as_json.to_json
|
189
|
+
end
|
190
|
+
end
|