mongo_mapper 0.6.10 → 0.7.0
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/README.rdoc +5 -14
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongo_mapper.rb +48 -56
- data/lib/mongo_mapper/document.rb +136 -164
- data/lib/mongo_mapper/embedded_document.rb +29 -354
- data/lib/mongo_mapper/plugins.rb +31 -0
- data/lib/mongo_mapper/plugins/associations.rb +105 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
- data/lib/mongo_mapper/plugins/clone.rb +13 -0
- data/lib/mongo_mapper/plugins/descendants.rb +16 -0
- data/lib/mongo_mapper/plugins/dirty.rb +119 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +324 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +24 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/rails.rb +45 -0
- data/lib/mongo_mapper/plugins/serialization.rb +105 -0
- data/lib/mongo_mapper/plugins/validations.rb +46 -0
- data/lib/mongo_mapper/query.rb +130 -0
- data/lib/mongo_mapper/support.rb +40 -17
- data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
- data/lib/mongo_mapper/support/find.rb +77 -0
- data/mongo_mapper.gemspec +55 -38
- data/performance/read_write.rb +52 -0
- data/specs.watchr +23 -2
- data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
- data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
- data/test/functional/associations/test_many_documents_proxy.rb +2 -8
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
- data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
- data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
- data/test/functional/associations/test_one_proxy.rb +25 -10
- data/test/functional/test_binary.rb +2 -8
- data/test/functional/test_callbacks.rb +1 -5
- data/test/functional/test_dirty.rb +27 -23
- data/test/functional/test_document.rb +224 -165
- data/test/functional/test_embedded_document.rb +72 -82
- data/test/functional/test_identity_map.rb +508 -0
- data/test/functional/test_modifiers.rb +15 -5
- data/test/functional/test_pagination.rb +1 -3
- data/test/functional/test_protected.rb +155 -0
- data/test/functional/test_string_id_compatibility.rb +7 -12
- data/test/functional/test_validations.rb +26 -58
- data/test/models.rb +0 -39
- data/test/test_helper.rb +37 -3
- data/test/unit/associations/test_base.rb +5 -5
- data/test/unit/associations/test_proxy.rb +8 -6
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +71 -76
- data/test/unit/test_dynamic_finder.rb +27 -29
- data/test/unit/test_embedded_document.rb +555 -601
- data/test/unit/{test_key.rb → test_keys.rb} +2 -5
- data/test/unit/test_mongo_mapper.rb +69 -9
- data/test/unit/test_pagination.rb +40 -32
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
- data/test/unit/test_rails.rb +123 -0
- data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
- data/test/unit/test_support.rb +23 -7
- data/test/unit/test_time_zones.rb +3 -4
- data/test/unit/test_validations.rb +58 -17
- metadata +53 -36
- data/lib/mongo_mapper/associations.rb +0 -78
- data/lib/mongo_mapper/associations/base.rb +0 -119
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
- data/lib/mongo_mapper/associations/collection.rb +0 -19
- data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
- data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
- data/lib/mongo_mapper/associations/proxy.rb +0 -116
- data/lib/mongo_mapper/callbacks.rb +0 -61
- data/lib/mongo_mapper/dirty.rb +0 -117
- data/lib/mongo_mapper/dynamic_finder.rb +0 -74
- data/lib/mongo_mapper/finder_options.rb +0 -145
- data/lib/mongo_mapper/key.rb +0 -36
- data/lib/mongo_mapper/mongo_mapper.rb +0 -125
- data/lib/mongo_mapper/pagination.rb +0 -66
- data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
- data/lib/mongo_mapper/serialization.rb +0 -54
- data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
- data/lib/mongo_mapper/validations.rb +0 -39
- data/test/functional/test_rails_compatibility.rb +0 -25
data/README.rdoc
CHANGED
@@ -13,25 +13,16 @@ Releases are tagged on github and released on gemcutter. Master is pushed to whe
|
|
13
13
|
* Send me a pull request. Bonus points for topic branches.
|
14
14
|
|
15
15
|
== Install
|
16
|
-
|
17
|
-
$ gem install mongo_mapper
|
18
|
-
|
19
|
-
== Dependencies
|
20
|
-
|
21
|
-
* ActiveSupport (typically the latest version)
|
22
|
-
* Mongo Ruby Driver (mongo)
|
23
|
-
* My fork of the validatable gem (jnunemaker-validatable)
|
24
16
|
|
25
|
-
|
17
|
+
$ gem install mongo_mapper
|
26
18
|
|
27
|
-
|
19
|
+
== Problems or Questions?
|
28
20
|
|
21
|
+
Hit up the google group.
|
29
22
|
http://groups.google.com/group/mongomapper
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
* http://www.mongodb.org/
|
34
|
-
* http://github.com/mongodb/mongo-ruby-driver/
|
24
|
+
To see if the problem you are having is a verified issue, you can see the MM pivotal tracker project:
|
25
|
+
http://www.pivotaltracker.com/projects/33576
|
35
26
|
|
36
27
|
== Copyright
|
37
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.18.
|
15
|
+
gem.add_dependency('mongo', '0.18.3')
|
16
16
|
gem.add_dependency('jnunemaker-validatable', '1.8.1')
|
17
17
|
|
18
18
|
gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/lib/mongo_mapper.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
# if Gem is defined i'll assume you are using rubygems and lock specific versions
|
2
4
|
# call me crazy but a plain old require will just get the latest version you have installed
|
3
5
|
# so i want to make sure that if you are using gems you do in fact have the correct versions
|
4
6
|
# if there is a better way to do this, please enlighten me!
|
5
7
|
if self.class.const_defined?(:Gem)
|
6
8
|
gem 'activesupport', '>= 2.3'
|
7
|
-
gem 'mongo', '0.18.
|
9
|
+
gem 'mongo', '0.18.3'
|
8
10
|
gem 'jnunemaker-validatable', '1.8.1'
|
9
11
|
end
|
10
12
|
|
@@ -15,112 +17,102 @@ require 'validatable'
|
|
15
17
|
module MongoMapper
|
16
18
|
# generic MM error
|
17
19
|
class MongoMapperError < StandardError; end
|
18
|
-
|
20
|
+
|
19
21
|
# raised when key expected to exist but not found
|
20
22
|
class KeyNotFound < MongoMapperError; end
|
21
|
-
|
23
|
+
|
22
24
|
# raised when document expected but not found
|
23
25
|
class DocumentNotFound < MongoMapperError; end
|
24
|
-
|
26
|
+
|
25
27
|
# raised when document not valid and using !
|
26
28
|
class DocumentNotValid < MongoMapperError
|
27
29
|
def initialize(document)
|
28
30
|
super("Validation failed: #{document.errors.full_messages.join(", ")}")
|
29
31
|
end
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
# @api public
|
33
35
|
def self.connection
|
34
36
|
@@connection ||= Mongo::Connection.new
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
# @api public
|
38
40
|
def self.connection=(new_connection)
|
39
41
|
@@connection = new_connection
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
# @api public
|
43
45
|
def self.logger
|
44
46
|
connection.logger
|
45
47
|
end
|
46
|
-
|
48
|
+
|
47
49
|
# @api public
|
48
50
|
def self.database=(name)
|
49
51
|
@@database = nil
|
50
52
|
@@database_name = name
|
51
53
|
end
|
52
|
-
|
54
|
+
|
53
55
|
# @api public
|
54
56
|
def self.database
|
55
57
|
if @@database_name.blank?
|
56
58
|
raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
@@database ||= MongoMapper.connection.db(@@database_name)
|
60
62
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@@ensured_indexes ||= []
|
63
|
+
|
64
|
+
def self.config=(hash)
|
65
|
+
@@config = hash
|
65
66
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@@
|
67
|
+
|
68
|
+
def self.config
|
69
|
+
raise 'Set config before connecting. MongoMapper.config = {...}' unless defined?(@@config)
|
70
|
+
@@config
|
70
71
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
|
73
|
+
def self.connect(environment, options={})
|
74
|
+
raise 'Set config before connecting. MongoMapper.config = {...}' if config.blank?
|
75
|
+
MongoMapper.connection = Mongo::Connection.new(config[environment]['host'], config[environment]['port'], options)
|
76
|
+
MongoMapper.database = config[environment]['database']
|
77
|
+
if config[environment]['username'].present? && config[environment]['password'].present?
|
78
|
+
MongoMapper.database.authenticate(config[environment]['username'], config[environment]['password'])
|
79
|
+
end
|
75
80
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
|
82
|
+
def self.setup(config, environment, options={})
|
83
|
+
using_passenger = options.delete(:passenger)
|
84
|
+
handle_passenger_forking if using_passenger
|
85
|
+
self.config = config
|
86
|
+
connect(environment, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.handle_passenger_forking
|
90
|
+
if defined?(PhusionPassenger)
|
91
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
92
|
+
connection.connect_to_master if forked
|
93
|
+
end
|
82
94
|
end
|
83
95
|
end
|
84
|
-
|
96
|
+
|
85
97
|
# @api private
|
86
98
|
def self.use_time_zone?
|
87
99
|
Time.respond_to?(:zone) && Time.zone ? true : false
|
88
100
|
end
|
89
|
-
|
101
|
+
|
90
102
|
# @api private
|
91
103
|
def self.time_class
|
92
104
|
use_time_zone? ? Time.zone : Time
|
93
105
|
end
|
94
|
-
|
106
|
+
|
95
107
|
# @api private
|
96
108
|
def self.normalize_object_id(value)
|
97
109
|
value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
|
98
110
|
end
|
111
|
+
|
112
|
+
autoload :Query, 'mongo_mapper/query'
|
113
|
+
autoload :Document, 'mongo_mapper/document'
|
114
|
+
autoload :EmbeddedDocument, 'mongo_mapper/embedded_document'
|
99
115
|
end
|
100
116
|
|
101
117
|
require 'mongo_mapper/support'
|
102
|
-
require 'mongo_mapper/
|
103
|
-
require 'mongo_mapper/finder_options'
|
104
|
-
require 'mongo_mapper/dirty'
|
105
|
-
require 'mongo_mapper/dynamic_finder'
|
106
|
-
require 'mongo_mapper/key'
|
107
|
-
require 'mongo_mapper/pagination'
|
108
|
-
require 'mongo_mapper/serialization'
|
109
|
-
require 'mongo_mapper/validations'
|
110
|
-
require 'mongo_mapper/rails_compatibility/document'
|
111
|
-
require 'mongo_mapper/rails_compatibility/embedded_document'
|
112
|
-
require 'mongo_mapper/embedded_document'
|
113
|
-
require 'mongo_mapper/document'
|
114
|
-
require 'mongo_mapper/associations'
|
115
|
-
require 'mongo_mapper/associations/base'
|
116
|
-
require 'mongo_mapper/associations/proxy'
|
117
|
-
require 'mongo_mapper/associations/collection'
|
118
|
-
require 'mongo_mapper/associations/many_documents_proxy'
|
119
|
-
require 'mongo_mapper/associations/belongs_to_proxy'
|
120
|
-
require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
|
121
|
-
require 'mongo_mapper/associations/many_polymorphic_proxy'
|
122
|
-
require 'mongo_mapper/associations/many_embedded_proxy'
|
123
|
-
require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
|
124
|
-
require 'mongo_mapper/associations/many_documents_as_proxy'
|
125
|
-
require 'mongo_mapper/associations/one_proxy'
|
126
|
-
require 'mongo_mapper/associations/in_array_proxy'
|
118
|
+
require 'mongo_mapper/plugins'
|
@@ -1,66 +1,39 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
1
|
module MongoMapper
|
4
2
|
module Document
|
3
|
+
extend Support::DescendantAppends
|
4
|
+
|
5
5
|
def self.included(model)
|
6
6
|
model.class_eval do
|
7
|
-
include EmbeddedDocument
|
8
7
|
include InstanceMethods
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
extra_extensions.concat extensions
|
33
|
-
|
34
|
-
# Add the extension to existing descendants
|
35
|
-
descendants.each do |model|
|
36
|
-
extensions.each { |extension| model.extend(extension) }
|
37
|
-
end
|
8
|
+
extend Support::Find
|
9
|
+
extend ClassMethods
|
10
|
+
extend Plugins
|
11
|
+
|
12
|
+
plugin Plugins::Associations
|
13
|
+
plugin Plugins::Clone
|
14
|
+
plugin Plugins::Descendants
|
15
|
+
plugin Plugins::Equality
|
16
|
+
plugin Plugins::Inspect
|
17
|
+
plugin Plugins::Keys
|
18
|
+
plugin Plugins::Dirty # for now dirty needs to be after keys
|
19
|
+
plugin Plugins::Logger
|
20
|
+
plugin Plugins::Pagination
|
21
|
+
plugin Plugins::Protected
|
22
|
+
plugin Plugins::Rails
|
23
|
+
plugin Plugins::Serialization
|
24
|
+
plugin Plugins::Validations
|
25
|
+
plugin Plugins::Callbacks # for now callbacks needs to be after validations
|
26
|
+
|
27
|
+
extend Plugins::Validations::DocumentMacros
|
28
|
+
end
|
29
|
+
|
30
|
+
super
|
38
31
|
end
|
39
32
|
|
40
|
-
# @api private
|
41
|
-
def self.extra_extensions
|
42
|
-
@extra_extensions ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.append_inclusions(*inclusions)
|
46
|
-
extra_inclusions.concat inclusions
|
47
|
-
|
48
|
-
# Add the inclusion to existing descendants
|
49
|
-
descendants.each do |model|
|
50
|
-
inclusions.each { |inclusion| model.send :include, inclusion }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# @api private
|
55
|
-
def self.extra_inclusions
|
56
|
-
@extra_inclusions ||= []
|
57
|
-
end
|
58
|
-
|
59
33
|
module ClassMethods
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
key
|
34
|
+
def inherited(subclass)
|
35
|
+
subclass.set_collection_name(collection_name)
|
36
|
+
super
|
64
37
|
end
|
65
38
|
|
66
39
|
def ensure_index(name_or_array, options={})
|
@@ -70,43 +43,50 @@ module MongoMapper
|
|
70
43
|
name_or_array
|
71
44
|
end
|
72
45
|
|
73
|
-
|
46
|
+
collection.create_index(keys_to_index, options[:unique])
|
47
|
+
end
|
48
|
+
|
49
|
+
def find(*args)
|
50
|
+
assert_no_first_last_or_all(args)
|
51
|
+
options = args.extract_options!
|
52
|
+
return nil if args.size == 0
|
53
|
+
|
54
|
+
if args.first.is_a?(Array) || args.size > 1
|
55
|
+
find_some(args, options)
|
56
|
+
else
|
57
|
+
find_one(options.merge({:_id => args[0]}))
|
58
|
+
end
|
74
59
|
end
|
75
60
|
|
76
61
|
def find!(*args)
|
62
|
+
assert_no_first_last_or_all(args)
|
77
63
|
options = args.extract_options!
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
case args.size
|
85
|
-
when 0
|
86
|
-
raise DocumentNotFound, "Couldn't find without an ID"
|
87
|
-
when 1
|
88
|
-
find_one!(options.merge({:_id => args[0]}))
|
89
|
-
else
|
90
|
-
find_some(args, options)
|
91
|
-
end
|
64
|
+
raise DocumentNotFound, "Couldn't find without an ID" if args.size == 0
|
65
|
+
|
66
|
+
if args.first.is_a?(Array) || args.size > 1
|
67
|
+
find_some!(args, options)
|
68
|
+
else
|
69
|
+
find_one(options.merge({:_id => args[0]})) || raise(DocumentNotFound, "Document match #{options.inspect} does not exist in #{collection.name} collection")
|
92
70
|
end
|
93
71
|
end
|
94
|
-
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
72
|
+
|
73
|
+
def find_each(options={})
|
74
|
+
criteria, options = to_query(options)
|
75
|
+
collection.find(criteria, options).each do |doc|
|
76
|
+
yield load(doc)
|
77
|
+
end
|
99
78
|
end
|
100
79
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
total_entries = count(options)
|
105
|
-
pagination = Pagination::PaginationProxy.new(total_entries, page, per_page)
|
80
|
+
def find_by_id(id)
|
81
|
+
find(id)
|
82
|
+
end
|
106
83
|
|
107
|
-
|
108
|
-
|
109
|
-
|
84
|
+
def first_or_create(arg)
|
85
|
+
first(arg) || create(arg)
|
86
|
+
end
|
87
|
+
|
88
|
+
def first_or_new(arg)
|
89
|
+
first(arg) || new(arg)
|
110
90
|
end
|
111
91
|
|
112
92
|
def first(options={})
|
@@ -119,11 +99,7 @@ module MongoMapper
|
|
119
99
|
end
|
120
100
|
|
121
101
|
def all(options={})
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
def find_by_id(id)
|
126
|
-
find(id)
|
102
|
+
find_many(options)
|
127
103
|
end
|
128
104
|
|
129
105
|
def count(options={})
|
@@ -160,63 +136,57 @@ module MongoMapper
|
|
160
136
|
end
|
161
137
|
|
162
138
|
def destroy(*ids)
|
163
|
-
find_some(ids.flatten).each(&:destroy)
|
139
|
+
find_some!(ids.flatten).each(&:destroy)
|
164
140
|
end
|
165
141
|
|
166
142
|
def destroy_all(options={})
|
167
|
-
|
143
|
+
find_each(options) { |document| document.destroy }
|
168
144
|
end
|
169
|
-
|
145
|
+
|
170
146
|
def increment(*args)
|
171
147
|
modifier_update('$inc', args)
|
172
148
|
end
|
173
|
-
|
149
|
+
|
174
150
|
def decrement(*args)
|
175
151
|
criteria, keys = criteria_and_keys_from_args(args)
|
176
152
|
values, to_decrement = keys.values, {}
|
177
153
|
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
|
178
154
|
collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
|
179
155
|
end
|
180
|
-
|
156
|
+
|
181
157
|
def set(*args)
|
182
158
|
modifier_update('$set', args)
|
183
159
|
end
|
184
|
-
|
160
|
+
|
185
161
|
def push(*args)
|
186
162
|
modifier_update('$push', args)
|
187
163
|
end
|
188
|
-
|
164
|
+
|
189
165
|
def push_all(*args)
|
190
166
|
modifier_update('$pushAll', args)
|
191
167
|
end
|
192
|
-
|
168
|
+
|
193
169
|
def push_uniq(*args)
|
194
170
|
criteria, keys = criteria_and_keys_from_args(args)
|
195
171
|
keys.each { |key, value | criteria[key] = {'$ne' => value} }
|
196
172
|
collection.update(criteria, {'$push' => keys}, :multi => true)
|
197
173
|
end
|
198
|
-
|
174
|
+
|
199
175
|
def pull(*args)
|
200
176
|
modifier_update('$pull', args)
|
201
177
|
end
|
202
|
-
|
178
|
+
|
203
179
|
def pull_all(*args)
|
204
180
|
modifier_update('$pullAll', args)
|
205
181
|
end
|
206
|
-
|
207
|
-
def
|
208
|
-
|
209
|
-
modifiers = {modifier => keys}
|
210
|
-
collection.update(criteria, modifiers, :multi => true)
|
182
|
+
|
183
|
+
def pop(*args)
|
184
|
+
modifier_update('$pop', args)
|
211
185
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
keys = args.pop
|
216
|
-
criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
|
217
|
-
[to_criteria(criteria), keys]
|
186
|
+
|
187
|
+
def embeddable?
|
188
|
+
false
|
218
189
|
end
|
219
|
-
private :criteria_and_keys_from_args
|
220
190
|
|
221
191
|
def connection(mongo_connection=nil)
|
222
192
|
if mongo_connection.nil?
|
@@ -269,39 +239,51 @@ module MongoMapper
|
|
269
239
|
end
|
270
240
|
|
271
241
|
def single_collection_inherited?
|
272
|
-
keys.
|
242
|
+
keys.key?(:_type) && single_collection_inherited_superclass?
|
273
243
|
end
|
274
244
|
|
275
245
|
def single_collection_inherited_superclass?
|
276
|
-
superclass.respond_to?(:keys) && superclass.keys.
|
246
|
+
superclass.respond_to?(:keys) && superclass.keys.key?(:_type)
|
277
247
|
end
|
278
248
|
|
279
249
|
private
|
280
|
-
def create_indexes_for(key)
|
281
|
-
ensure_index key.name if key.options[:index]
|
282
|
-
end
|
283
|
-
|
284
250
|
def initialize_each(*docs)
|
285
251
|
instances = []
|
286
252
|
docs = [{}] if docs.blank?
|
287
253
|
docs.flatten.each do |attrs|
|
288
|
-
doc =
|
254
|
+
doc = new(attrs)
|
289
255
|
yield(doc)
|
290
256
|
instances << doc
|
291
257
|
end
|
292
258
|
instances.size == 1 ? instances[0] : instances
|
293
259
|
end
|
294
260
|
|
295
|
-
def
|
296
|
-
criteria,
|
297
|
-
|
298
|
-
|
261
|
+
def modifier_update(modifier, args)
|
262
|
+
criteria, keys = criteria_and_keys_from_args(args)
|
263
|
+
modifiers = {modifier => keys}
|
264
|
+
collection.update(criteria, modifiers, :multi => true)
|
265
|
+
end
|
266
|
+
|
267
|
+
def criteria_and_keys_from_args(args)
|
268
|
+
keys = args.pop
|
269
|
+
criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
|
270
|
+
[to_criteria(criteria), keys]
|
271
|
+
end
|
272
|
+
|
273
|
+
def assert_no_first_last_or_all(args)
|
274
|
+
if args[0] == :first || args[0] == :last || args[0] == :all
|
275
|
+
raise ArgumentError, "#{self}.find(:#{args}) is no longer supported, use #{self}.#{args} instead."
|
299
276
|
end
|
300
277
|
end
|
301
278
|
|
302
279
|
def find_some(ids, options={})
|
303
|
-
ids
|
304
|
-
|
280
|
+
ids = ids.flatten.compact.uniq
|
281
|
+
find_many(options.merge(:_id => ids)).compact
|
282
|
+
end
|
283
|
+
|
284
|
+
def find_some!(ids, options={})
|
285
|
+
ids = ids.flatten.compact.uniq
|
286
|
+
documents = find_some(ids, options)
|
305
287
|
|
306
288
|
if ids.size == documents.size
|
307
289
|
documents
|
@@ -310,15 +292,20 @@ module MongoMapper
|
|
310
292
|
end
|
311
293
|
end
|
312
294
|
|
295
|
+
# All query methods that load documents pass through find_one or find_many
|
313
296
|
def find_one(options={})
|
314
|
-
criteria, options =
|
297
|
+
criteria, options = to_query(options)
|
315
298
|
if doc = collection.find_one(criteria, options)
|
316
|
-
|
299
|
+
load(doc)
|
317
300
|
end
|
318
301
|
end
|
319
302
|
|
320
|
-
|
321
|
-
|
303
|
+
# All query methods that load documents pass through find_one or find_many
|
304
|
+
def find_many(options)
|
305
|
+
criteria, options = to_query(options)
|
306
|
+
collection.find(criteria, options).to_a.map do |doc|
|
307
|
+
load(doc)
|
308
|
+
end
|
322
309
|
end
|
323
310
|
|
324
311
|
def invert_order_clause(order)
|
@@ -354,11 +341,11 @@ module MongoMapper
|
|
354
341
|
end
|
355
342
|
|
356
343
|
def to_criteria(options={})
|
357
|
-
|
344
|
+
Query.new(self, options).criteria
|
358
345
|
end
|
359
346
|
|
360
|
-
def
|
361
|
-
|
347
|
+
def to_query(options={})
|
348
|
+
Query.new(self, options).to_a
|
362
349
|
end
|
363
350
|
end
|
364
351
|
|
@@ -366,42 +353,38 @@ module MongoMapper
|
|
366
353
|
def collection
|
367
354
|
self.class.collection
|
368
355
|
end
|
369
|
-
|
356
|
+
|
370
357
|
def database
|
371
358
|
self.class.database
|
372
359
|
end
|
373
360
|
|
374
|
-
def new?
|
375
|
-
read_attribute('_id').blank? || using_custom_id?
|
376
|
-
end
|
377
|
-
|
378
361
|
def save(options={})
|
379
|
-
|
380
|
-
ActiveSupport::Deprecation.warn "save with true/false is deprecated. You should now use :validate => true/false."
|
381
|
-
options = {:validate => false}
|
382
|
-
end
|
362
|
+
options.assert_valid_keys(:validate, :safe)
|
383
363
|
options.reverse_merge!(:validate => true)
|
384
|
-
|
385
|
-
!perform_validations || valid? ? create_or_update(options) : false
|
364
|
+
!options[:validate] || valid? ? create_or_update(options) : false
|
386
365
|
end
|
387
366
|
|
388
|
-
def save!
|
389
|
-
|
367
|
+
def save!(options={})
|
368
|
+
options.assert_valid_keys(:safe)
|
369
|
+
save(options) || raise(DocumentNotValid.new(self))
|
390
370
|
end
|
391
371
|
|
392
372
|
def destroy
|
393
|
-
|
373
|
+
delete
|
394
374
|
end
|
395
|
-
|
375
|
+
|
396
376
|
def delete
|
397
377
|
self.class.delete(id) unless new?
|
398
378
|
end
|
399
379
|
|
400
380
|
def reload
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
381
|
+
if attrs = collection.find_one({:_id => _id})
|
382
|
+
self.class.associations.each { |name, assoc| send(name).reset if respond_to?(name) }
|
383
|
+
self.attributes = attrs
|
384
|
+
self
|
385
|
+
else
|
386
|
+
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
387
|
+
end
|
405
388
|
end
|
406
389
|
|
407
390
|
private
|
@@ -411,34 +394,23 @@ module MongoMapper
|
|
411
394
|
end
|
412
395
|
|
413
396
|
def create(options={})
|
414
|
-
assign_id
|
415
397
|
save_to_collection(options)
|
416
398
|
end
|
417
399
|
|
418
|
-
def assign_id
|
419
|
-
if read_attribute(:_id).blank?
|
420
|
-
write_attribute :_id, Mongo::ObjectID.new
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
400
|
def update(options={})
|
425
401
|
save_to_collection(options)
|
426
402
|
end
|
427
403
|
|
428
404
|
def save_to_collection(options={})
|
429
|
-
|
430
|
-
|
405
|
+
safe = options[:safe] || false
|
406
|
+
@new = false
|
431
407
|
collection.save(to_mongo, :safe => safe)
|
432
408
|
end
|
433
409
|
|
434
410
|
def update_timestamps
|
435
411
|
now = Time.now.utc
|
436
|
-
|
437
|
-
|
438
|
-
end
|
439
|
-
|
440
|
-
def clear_custom_id_flag
|
441
|
-
@using_custom_id = nil
|
412
|
+
self[:created_at] = now if new? && !created_at?
|
413
|
+
self[:updated_at] = now
|
442
414
|
end
|
443
415
|
end
|
444
416
|
end # Document
|