mongo_mapper-unstable 2009.11.8 → 2009.11.18
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.
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/bin/mmconsole +10 -5
- data/lib/mongo_mapper.rb +28 -5
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +1 -1
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +1 -1
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +2 -2
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +2 -2
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +2 -1
- data/lib/mongo_mapper/document.rb +3 -12
- data/lib/mongo_mapper/embedded_document.rb +37 -19
- data/lib/mongo_mapper/finder_options.rb +17 -11
- data/lib/mongo_mapper/rails_compatibility/document.rb +4 -0
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +4 -0
- data/lib/mongo_mapper/serializers/json_serializer.rb +2 -2
- data/lib/mongo_mapper/support.rb +16 -44
- data/lib/mongo_mapper/types.rb +64 -0
- data/lib/mongo_mapper/validations.rb +1 -1
- data/mongo_mapper.gemspec +15 -12
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +10 -10
- data/test/functional/associations/test_belongs_to_proxy.rb +2 -1
- data/test/functional/associations/test_many_documents_as_proxy.rb +13 -12
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +34 -34
- data/test/functional/associations/test_many_embedded_proxy.rb +22 -22
- data/test/functional/associations/test_many_polymorphic_proxy.rb +10 -10
- data/test/functional/associations/test_many_proxy.rb +14 -15
- data/test/functional/test_associations.rb +4 -4
- data/test/functional/test_binary.rb +1 -1
- data/test/functional/test_dirty.rb +6 -6
- data/test/functional/test_document.rb +64 -65
- data/test/functional/test_embedded_document.rb +34 -14
- data/test/functional/test_string_id_compatibility.rb +72 -0
- data/test/functional/test_validations.rb +1 -1
- data/test/models.rb +24 -24
- data/test/unit/test_document.rb +7 -4
- data/test/unit/test_embedded_document.rb +47 -5
- data/test/unit/test_finder_options.rb +22 -3
- data/test/unit/test_mongo_mapper.rb +65 -0
- data/test/unit/test_rails_compatibility.rb +14 -0
- data/test/unit/test_support.rb +45 -0
- metadata +8 -5
- data/test/unit/test_mongomapper.rb +0 -28
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ Jeweler::Tasks.new do |gem|
|
|
12
12
|
gem.authors = ["John Nunemaker"]
|
13
13
|
|
14
14
|
gem.add_dependency('activesupport', '>= 2.3')
|
15
|
-
gem.add_dependency('mongo', '0.
|
15
|
+
gem.add_dependency('mongo', '0.17.1')
|
16
16
|
gem.add_dependency('jnunemaker-validatable', '1.8.1')
|
17
17
|
|
18
18
|
gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
|
@@ -51,5 +51,5 @@ task :default => :test
|
|
51
51
|
task :test => :check_dependencies
|
52
52
|
|
53
53
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
54
|
-
t.options = ["--legacy"]
|
55
|
-
end
|
54
|
+
t.options = ["--legacy"] if RUBY_VERSION < "1.9.0"
|
55
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2009.11.
|
1
|
+
2009.11.18
|
data/bin/mmconsole
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
$:.unshift
|
3
|
-
|
4
|
-
|
5
|
-
require '
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'mongo_mapper'
|
6
|
+
require 'irb'
|
7
|
+
rescue LoadError
|
8
|
+
require 'rubygems'
|
9
|
+
retry
|
10
|
+
end
|
6
11
|
|
7
12
|
IRB.setup(nil)
|
8
13
|
irb = IRB::Irb.new
|
@@ -43,12 +48,12 @@ Example 2:
|
|
43
48
|
|
44
49
|
all_things = Thing.all
|
45
50
|
puts all_things.map { |object| object.name }.inspect
|
46
|
-
|
47
51
|
@
|
48
52
|
|
49
53
|
trap("SIGINT") do
|
50
54
|
irb.signal_handle
|
51
55
|
end
|
56
|
+
|
52
57
|
catch(:IRB_EXIT) do
|
53
58
|
irb.eval_input
|
54
59
|
end
|
data/lib/mongo_mapper.rb
CHANGED
@@ -15,28 +15,32 @@ module MongoMapper
|
|
15
15
|
# raised when document not valid and using !
|
16
16
|
class DocumentNotValid < MongoMapperError
|
17
17
|
def initialize(document)
|
18
|
-
|
19
|
-
super("Validation failed: #{@document.errors.full_messages.join(", ")}")
|
18
|
+
super("Validation failed: #{document.errors.full_messages.join(", ")}")
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
22
|
+
# @api public
|
23
23
|
def self.connection
|
24
24
|
@@connection ||= Mongo::Connection.new
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
|
+
# @api public
|
27
28
|
def self.connection=(new_connection)
|
28
29
|
@@connection = new_connection
|
29
30
|
end
|
30
31
|
|
32
|
+
# @api public
|
31
33
|
def self.logger
|
32
34
|
connection.logger
|
33
35
|
end
|
34
|
-
|
36
|
+
|
37
|
+
# @api public
|
35
38
|
def self.database=(name)
|
36
39
|
@@database = nil
|
37
40
|
@@database_name = name
|
38
41
|
end
|
39
|
-
|
42
|
+
|
43
|
+
# @api public
|
40
44
|
def self.database
|
41
45
|
if @@database_name.blank?
|
42
46
|
raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
|
@@ -45,14 +49,17 @@ module MongoMapper
|
|
45
49
|
@@database ||= MongoMapper.connection.db(@@database_name)
|
46
50
|
end
|
47
51
|
|
52
|
+
# @api private
|
48
53
|
def self.ensured_indexes
|
49
54
|
@@ensured_indexes ||= []
|
50
55
|
end
|
51
56
|
|
57
|
+
# @api private
|
52
58
|
def self.ensure_index(klass, keys, options={})
|
53
59
|
ensured_indexes << {:klass => klass, :keys => keys, :options => options}
|
54
60
|
end
|
55
61
|
|
62
|
+
# @api public
|
56
63
|
def self.ensure_indexes!
|
57
64
|
ensured_indexes.each do |index|
|
58
65
|
unique = index[:options].delete(:unique)
|
@@ -60,6 +67,7 @@ module MongoMapper
|
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
70
|
+
# @api private
|
63
71
|
module Finders
|
64
72
|
def dynamic_find(finder, args)
|
65
73
|
attributes = {}
|
@@ -83,9 +91,24 @@ module MongoMapper
|
|
83
91
|
end
|
84
92
|
end
|
85
93
|
end
|
94
|
+
|
95
|
+
# @api private
|
96
|
+
def self.use_time_zone?
|
97
|
+
Time.respond_to?(:zone) && Time.zone ? true : false
|
98
|
+
end
|
99
|
+
|
100
|
+
# @api private
|
101
|
+
def self.time_class
|
102
|
+
use_time_zone? ? Time.zone : Time
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.normalize_object_id(value)
|
106
|
+
value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
|
107
|
+
end
|
86
108
|
end
|
87
109
|
|
88
110
|
require 'mongo_mapper/support'
|
111
|
+
require 'mongo_mapper/types'
|
89
112
|
require 'mongo_mapper/associations'
|
90
113
|
require 'mongo_mapper/associations/base'
|
91
114
|
require 'mongo_mapper/associations/proxy'
|
@@ -3,13 +3,13 @@ module MongoMapper
|
|
3
3
|
class ManyDocumentsAsProxy < ManyDocumentsProxy
|
4
4
|
protected
|
5
5
|
def scoped_conditions
|
6
|
-
{as_type_name => @owner.class.name, as_id_name => @owner.
|
6
|
+
{as_type_name => @owner.class.name, as_id_name => @owner._id}
|
7
7
|
end
|
8
8
|
|
9
9
|
def apply_scope(doc)
|
10
10
|
ensure_owner_saved
|
11
11
|
doc.send("#{as_type_name}=", @owner.class.name)
|
12
|
-
doc.send("#{as_id_name}=", @owner.
|
12
|
+
doc.send("#{as_id_name}=", @owner._id)
|
13
13
|
doc
|
14
14
|
end
|
15
15
|
|
@@ -98,7 +98,7 @@ module MongoMapper
|
|
98
98
|
|
99
99
|
protected
|
100
100
|
def scoped_conditions
|
101
|
-
{self.foreign_key => @owner.
|
101
|
+
{self.foreign_key => @owner._id}
|
102
102
|
end
|
103
103
|
|
104
104
|
def scoped_options(options)
|
@@ -115,7 +115,7 @@ module MongoMapper
|
|
115
115
|
|
116
116
|
def apply_scope(doc)
|
117
117
|
ensure_owner_saved
|
118
|
-
doc.send("#{self.foreign_key}=", @owner.
|
118
|
+
doc.send("#{self.foreign_key}=", @owner._id)
|
119
119
|
doc
|
120
120
|
end
|
121
121
|
|
@@ -13,9 +13,10 @@ module MongoMapper
|
|
13
13
|
doc
|
14
14
|
end
|
15
15
|
|
16
|
+
# TODO: test that both string and oid version work
|
16
17
|
def find(id)
|
17
18
|
load_target
|
18
|
-
@target.detect { |item| item.id == id }
|
19
|
+
@target.detect { |item| item.id == id || item._id == id }
|
19
20
|
end
|
20
21
|
|
21
22
|
def <<(*docs)
|
@@ -344,15 +344,6 @@ module MongoMapper
|
|
344
344
|
instances.size == 1 ? instances[0] : instances
|
345
345
|
end
|
346
346
|
|
347
|
-
def initialize_doc(doc)
|
348
|
-
begin
|
349
|
-
klass = doc['_type'].present? ? doc['_type'].constantize : self
|
350
|
-
klass.new(doc)
|
351
|
-
rescue NameError
|
352
|
-
new(doc)
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
347
|
def find_every(options)
|
357
348
|
criteria, options = to_finder_options(options)
|
358
349
|
collection.find(criteria, options).to_a.map do |doc|
|
@@ -442,12 +433,12 @@ module MongoMapper
|
|
442
433
|
|
443
434
|
def destroy
|
444
435
|
return false if frozen?
|
445
|
-
self.class.delete(
|
436
|
+
self.class.delete(_id) unless new?
|
446
437
|
freeze
|
447
438
|
end
|
448
439
|
|
449
440
|
def reload
|
450
|
-
self.class.find(
|
441
|
+
self.class.find(_id)
|
451
442
|
end
|
452
443
|
|
453
444
|
private
|
@@ -463,7 +454,7 @@ module MongoMapper
|
|
463
454
|
|
464
455
|
def assign_id
|
465
456
|
if read_attribute(:_id).blank?
|
466
|
-
write_attribute
|
457
|
+
write_attribute :_id, Mongo::ObjectID.new
|
467
458
|
end
|
468
459
|
end
|
469
460
|
|
@@ -16,7 +16,7 @@ module MongoMapper
|
|
16
16
|
|
17
17
|
extend Validations::Macros
|
18
18
|
|
19
|
-
key :_id,
|
19
|
+
key :_id, ObjectId
|
20
20
|
attr_accessor :_root_document
|
21
21
|
end
|
22
22
|
end
|
@@ -25,7 +25,7 @@ module MongoMapper
|
|
25
25
|
def logger
|
26
26
|
MongoMapper.logger
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def inherited(subclass)
|
30
30
|
unless subclass.embeddable?
|
31
31
|
subclass.set_collection_name(collection_name)
|
@@ -48,19 +48,23 @@ module MongoMapper
|
|
48
48
|
|
49
49
|
def key(*args)
|
50
50
|
key = Key.new(*args)
|
51
|
+
keys[key.name] = key
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
create_accessors_for(key)
|
54
|
+
create_key_in_subclasses(*args)
|
55
|
+
create_validations_for(key)
|
54
56
|
|
55
|
-
create_accessors_for(key)
|
56
|
-
create_key_in_subclasses(*args)
|
57
|
-
create_validations_for(key)
|
58
|
-
|
59
|
-
key
|
60
|
-
end
|
61
|
-
|
62
57
|
key
|
63
58
|
end
|
59
|
+
|
60
|
+
def using_object_id?
|
61
|
+
object_id_key?(:_id)
|
62
|
+
end
|
63
|
+
|
64
|
+
def object_id_key?(name)
|
65
|
+
key = keys[name.to_s]
|
66
|
+
key && key.type == ObjectId
|
67
|
+
end
|
64
68
|
|
65
69
|
def embeddable?
|
66
70
|
!self.ancestors.include?(Document)
|
@@ -83,11 +87,20 @@ module MongoMapper
|
|
83
87
|
if instance_or_hash.is_a?(self)
|
84
88
|
instance_or_hash
|
85
89
|
else
|
86
|
-
|
90
|
+
initialize_doc(instance_or_hash)
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
90
94
|
private
|
95
|
+
def initialize_doc(doc)
|
96
|
+
begin
|
97
|
+
klass = doc['_type'].present? ? doc['_type'].constantize : self
|
98
|
+
klass.new(doc)
|
99
|
+
rescue NameError
|
100
|
+
new(doc)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
91
104
|
def accessors_module
|
92
105
|
module_defined = if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
|
93
106
|
const_defined?('MongoMapperKeys')
|
@@ -191,16 +204,16 @@ module MongoMapper
|
|
191
204
|
end
|
192
205
|
end
|
193
206
|
|
194
|
-
if self.class.embeddable?
|
207
|
+
if self.class.embeddable?
|
195
208
|
if read_attribute(:_id).blank?
|
196
|
-
write_attribute :_id, Mongo::ObjectID.new
|
209
|
+
write_attribute :_id, Mongo::ObjectID.new
|
197
210
|
@new_document = true
|
198
211
|
else
|
199
212
|
@new_document = false
|
200
213
|
end
|
201
214
|
end
|
202
215
|
end
|
203
|
-
|
216
|
+
|
204
217
|
def new?
|
205
218
|
!!@new_document
|
206
219
|
end
|
@@ -275,15 +288,20 @@ module MongoMapper
|
|
275
288
|
end
|
276
289
|
|
277
290
|
def ==(other)
|
278
|
-
other.is_a?(self.class) &&
|
291
|
+
other.is_a?(self.class) && _id == other._id
|
279
292
|
end
|
280
293
|
|
281
294
|
def id
|
282
|
-
read_attribute(:_id)
|
295
|
+
read_attribute(:_id).to_s
|
283
296
|
end
|
284
297
|
|
285
298
|
def id=(value)
|
286
|
-
|
299
|
+
if self.class.using_object_id?
|
300
|
+
value = MongoMapper.normalize_object_id(value)
|
301
|
+
else
|
302
|
+
@using_custom_id = true
|
303
|
+
end
|
304
|
+
|
287
305
|
write_attribute :_id, value
|
288
306
|
end
|
289
307
|
|
@@ -353,7 +371,7 @@ module MongoMapper
|
|
353
371
|
def write_attribute(name, value)
|
354
372
|
key = _keys[name]
|
355
373
|
instance_variable_set "@#{name}_before_typecast", value
|
356
|
-
instance_variable_set "@#{name}", key.set(value)
|
374
|
+
instance_variable_set "@#{name}", key.set(value)
|
357
375
|
end
|
358
376
|
|
359
377
|
def embedded_associations
|
@@ -8,17 +8,7 @@ module MongoMapper
|
|
8
8
|
# useful for understanding how MongoMapper handles the parsing of finder
|
9
9
|
# conditions and options.
|
10
10
|
#
|
11
|
-
# @private
|
12
|
-
class FinderOperator
|
13
|
-
def initialize(field, operator)
|
14
|
-
@field, @operator = field, operator
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_criteria(value)
|
18
|
-
{@field => {@operator => value}}
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
11
|
+
# @private
|
22
12
|
class FinderOptions
|
23
13
|
OptionKeys = [:fields, :select, :skip, :offset, :limit, :sort, :order]
|
24
14
|
|
@@ -72,10 +62,16 @@ module MongoMapper
|
|
72
62
|
|
73
63
|
conditions.each_pair do |field, value|
|
74
64
|
field = normalized_field(field)
|
65
|
+
|
66
|
+
if @model.object_id_key?(field) && value.is_a?(String)
|
67
|
+
value = Mongo::ObjectID.from_string(value)
|
68
|
+
end
|
69
|
+
|
75
70
|
if field.is_a?(FinderOperator)
|
76
71
|
criteria.merge!(field.to_criteria(value))
|
77
72
|
next
|
78
73
|
end
|
74
|
+
|
79
75
|
case value
|
80
76
|
when Array
|
81
77
|
operator_present = field.to_s =~ /^\$/
|
@@ -128,4 +124,14 @@ module MongoMapper
|
|
128
124
|
[field, direction]
|
129
125
|
end
|
130
126
|
end
|
127
|
+
|
128
|
+
class FinderOperator
|
129
|
+
def initialize(field, operator)
|
130
|
+
@field, @operator = field, operator
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_criteria(value)
|
134
|
+
{@field => {@operator => value}}
|
135
|
+
end
|
136
|
+
end
|
131
137
|
end
|