mongoid 2.0.0.beta.9 → 2.0.0.beta.10
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 +2 -4
- data/lib/mongoid.rb +2 -1
- data/lib/mongoid/associations.rb +2 -3
- data/lib/mongoid/associations/embeds_many.rb +6 -2
- data/lib/mongoid/associations/embeds_one.rb +1 -3
- data/lib/mongoid/associations/options.rb +11 -10
- data/lib/mongoid/associations/references_many.rb +27 -4
- data/lib/mongoid/associations/references_many_as_array.rb +24 -4
- data/lib/mongoid/associations/references_one.rb +1 -2
- data/lib/mongoid/atomicity.rb +17 -4
- data/lib/mongoid/config.rb +97 -20
- data/lib/mongoid/contexts/enumerable.rb +9 -4
- data/lib/mongoid/contexts/mongo.rb +1 -1
- data/lib/mongoid/criteria.rb +7 -1
- data/lib/mongoid/criterion/inclusion.rb +12 -5
- data/lib/mongoid/criterion/optional.rb +26 -3
- data/lib/mongoid/cursor.rb +0 -1
- data/lib/mongoid/deprecation.rb +1 -2
- data/lib/mongoid/document.rb +25 -3
- data/lib/mongoid/extensions.rb +2 -1
- data/lib/mongoid/extensions/float/conversions.rb +1 -1
- data/lib/mongoid/extensions/integer/conversions.rb +1 -1
- data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
- data/lib/mongoid/finders.rb +3 -2
- data/lib/mongoid/indexes.rb +17 -6
- data/lib/mongoid/logger.rb +19 -0
- data/lib/mongoid/paranoia.rb +12 -14
- data/lib/mongoid/persistence/remove_embedded.rb +0 -4
- data/lib/mongoid/persistence/update.rb +3 -0
- data/lib/mongoid/railtie.rb +37 -4
- data/lib/mongoid/railties/database.rake +19 -1
- data/lib/mongoid/validations/associated.rb +1 -1
- data/lib/mongoid/validations/locale/en.yml +4 -3
- data/lib/mongoid/validations/uniqueness.rb +19 -8
- data/lib/mongoid/version.rb +1 -1
- metadata +50 -18
- data/lib/mongoid/extensions/array/aliasing.rb +0 -4
@@ -36,7 +36,7 @@ module Mongoid #:nodoc:
|
|
36
36
|
|
37
37
|
# Gets the number of documents in the array. Delegates to size.
|
38
38
|
def count
|
39
|
-
@count ||=
|
39
|
+
@count ||= filter.size
|
40
40
|
end
|
41
41
|
|
42
42
|
# Gets an array of distinct values for the supplied field across the
|
@@ -56,7 +56,7 @@ module Mongoid #:nodoc:
|
|
56
56
|
#
|
57
57
|
# An +Array+ of documents that matched the selector.
|
58
58
|
def execute(paginating = false)
|
59
|
-
limit(
|
59
|
+
limit(filter) || []
|
60
60
|
end
|
61
61
|
|
62
62
|
# Groups the documents by the first field supplied in the field options.
|
@@ -66,7 +66,7 @@ module Mongoid #:nodoc:
|
|
66
66
|
# A +Hash+ with field values as keys, arrays of documents as values.
|
67
67
|
def group
|
68
68
|
field = options[:fields].first
|
69
|
-
|
69
|
+
execute.group_by { |doc| doc.send(field) }
|
70
70
|
end
|
71
71
|
|
72
72
|
# Create the new enumerable context. This will need the selector and
|
@@ -121,13 +121,18 @@ module Mongoid #:nodoc:
|
|
121
121
|
#
|
122
122
|
# The numerical sum of all the document field values.
|
123
123
|
def sum(field)
|
124
|
-
sum =
|
124
|
+
sum = execute.inject(nil) do |memo, doc|
|
125
125
|
value = doc.send(field)
|
126
126
|
memo ? memo += value : value
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
130
|
protected
|
131
|
+
# Filters the documents against the criteria's selector
|
132
|
+
def filter
|
133
|
+
documents.select { |document| document.matches?(selector) }
|
134
|
+
end
|
135
|
+
|
131
136
|
# If the field exists, perform the comparison and set if true.
|
132
137
|
def determine(field, operator)
|
133
138
|
matching = documents.inject(nil) do |memo, doc|
|
@@ -133,7 +133,7 @@ module Mongoid #:nodoc:
|
|
133
133
|
# <tt>Mongoid::Contexts::Mongo.new(criteria)</tt>
|
134
134
|
def initialize(criteria)
|
135
135
|
@criteria = criteria
|
136
|
-
if klass.hereditary
|
136
|
+
if klass.hereditary && !criteria.selector.keys.include?(:_type)
|
137
137
|
criteria.in(:_type => criteria.klass._types)
|
138
138
|
end
|
139
139
|
criteria.enslave if klass.enslaved?
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -63,6 +63,12 @@ module Mongoid #:nodoc:
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
# Returns true if the supplied +Object+ is an instance of +Criteria+ or
|
67
|
+
# +Scope+.
|
68
|
+
def self.===(other)
|
69
|
+
super || Scope === other
|
70
|
+
end
|
71
|
+
|
66
72
|
# Return or create the context in which this criteria should be executed.
|
67
73
|
#
|
68
74
|
# This will return an Enumerable context if the class is embedded,
|
@@ -148,7 +154,7 @@ module Mongoid #:nodoc:
|
|
148
154
|
def method_missing(name, *args)
|
149
155
|
if @klass.respond_to?(name)
|
150
156
|
new_scope = @klass.send(name, *args)
|
151
|
-
new_scope.merge(self)
|
157
|
+
new_scope.merge(self) if Criteria === new_scope
|
152
158
|
return new_scope
|
153
159
|
else
|
154
160
|
return entries.send(name, *args)
|
@@ -97,12 +97,19 @@ module Mongoid #:nodoc:
|
|
97
97
|
#
|
98
98
|
# Returns: <tt>self</tt>
|
99
99
|
def where(selector = nil)
|
100
|
-
case selector
|
101
|
-
|
102
|
-
|
103
|
-
else
|
104
|
-
@selector.update(selector ? selector.expand_complex_criteria : {})
|
100
|
+
selector = case selector
|
101
|
+
when String then {"$where" => selector}
|
102
|
+
else selector ? selector.expand_complex_criteria : {}
|
105
103
|
end
|
104
|
+
|
105
|
+
selector.each_pair do |key, value|
|
106
|
+
if @selector.has_key?(key) && @selector[key].respond_to?(:merge!)
|
107
|
+
@selector[key].merge!(value)
|
108
|
+
else
|
109
|
+
@selector[key] = value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
106
113
|
self
|
107
114
|
end
|
108
115
|
end
|
@@ -91,15 +91,21 @@ module Mongoid #:nodoc:
|
|
91
91
|
#
|
92
92
|
# Options:
|
93
93
|
#
|
94
|
-
# object_id: A +String+
|
94
|
+
# object_id: A single id or an array of ids in +String+ or <tt>BSON::ObjectID</tt> format
|
95
95
|
#
|
96
96
|
# Example:
|
97
97
|
#
|
98
98
|
# <tt>criteria.id("4ab2bc4b8ad548971900005c")</tt>
|
99
|
+
# <tt>criteria.id(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"])</tt>
|
99
100
|
#
|
100
101
|
# Returns: <tt>self</tt>
|
101
|
-
def id(*
|
102
|
-
|
102
|
+
def id(*ids)
|
103
|
+
ids.flatten!
|
104
|
+
if ids.size > 1
|
105
|
+
self.in(:_id => Mongoid.convert_to_object_id(ids, self.klass.primary_key.nil?))
|
106
|
+
else
|
107
|
+
@selector[:_id] = Mongoid.convert_to_object_id(ids.first, self.klass.primary_key.nil?)
|
108
|
+
end
|
103
109
|
self
|
104
110
|
end
|
105
111
|
|
@@ -167,6 +173,23 @@ module Mongoid #:nodoc:
|
|
167
173
|
def skip(value = 0)
|
168
174
|
@options[:skip] = value; self
|
169
175
|
end
|
176
|
+
|
177
|
+
# Adds a criterion to the +Criteria+ that specifies a type or an Array of type that must be matched.
|
178
|
+
#
|
179
|
+
# Options:
|
180
|
+
#
|
181
|
+
# types : An +Array+ of types of a +String+ representing the Type of you search
|
182
|
+
#
|
183
|
+
# Example:
|
184
|
+
#
|
185
|
+
# <tt>criteria.type('Browser')</tt>
|
186
|
+
# <tt>criteria.type(['Firefox', 'Browser'])</tt>
|
187
|
+
#
|
188
|
+
# Returns: <tt>self</tt>
|
189
|
+
def type(types)
|
190
|
+
types = [types] unless types.is_a?(Array)
|
191
|
+
self.in(:_type => types)
|
192
|
+
end
|
170
193
|
end
|
171
194
|
end
|
172
195
|
end
|
data/lib/mongoid/cursor.rb
CHANGED
data/lib/mongoid/deprecation.rb
CHANGED
@@ -14,9 +14,8 @@ module Mongoid #:nodoc:
|
|
14
14
|
end
|
15
15
|
|
16
16
|
protected
|
17
|
-
# Instantiate a new logger to stdout or a rails logger if available.
|
18
17
|
def initialize
|
19
|
-
@logger =
|
18
|
+
@logger = Mongoid::Logger.new
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
data/lib/mongoid/document.rb
CHANGED
@@ -11,6 +11,10 @@ module Mongoid #:nodoc:
|
|
11
11
|
attr_reader :new_record
|
12
12
|
|
13
13
|
delegate :primary_key, :to => "self.class"
|
14
|
+
|
15
|
+
unless self.instance_of?(Class) and self.name == ""
|
16
|
+
(@@descendants ||= {})[self] = :seen
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
module ClassMethods #:nodoc:
|
@@ -58,12 +62,17 @@ module Mongoid #:nodoc:
|
|
58
62
|
set_callback :save, :before, :identify
|
59
63
|
end
|
60
64
|
|
65
|
+
# Returns the classes that have included Mongoid::Document
|
66
|
+
def self.descendents
|
67
|
+
(@@descendants ||= {}).keys
|
68
|
+
end
|
69
|
+
|
61
70
|
# Returns all types to query for when using this class as the base.
|
62
71
|
# *subclasses* is from activesupport. Note that a bug in *subclasses*
|
63
72
|
# causes the first call to only return direct children, hence
|
64
73
|
# the double call and unique.
|
65
74
|
def _types
|
66
|
-
@_type ||= [subclasses + subclasses + [self.name]].flatten.uniq
|
75
|
+
@_type ||= [subclasses + subclasses + [self.name]].flatten.uniq.map(&:to_s)
|
67
76
|
end
|
68
77
|
end
|
69
78
|
|
@@ -169,10 +178,23 @@ module Mongoid #:nodoc:
|
|
169
178
|
# memoized association and notify the parent of the change.
|
170
179
|
def remove(child)
|
171
180
|
name = child.association_name
|
172
|
-
|
173
|
-
|
181
|
+
if @building_nested
|
182
|
+
@attributes.remove(name, child.raw_attributes)
|
183
|
+
else
|
184
|
+
reset(name) do
|
185
|
+
@attributes.remove(name, child.raw_attributes)
|
186
|
+
@attributes[name]
|
187
|
+
end
|
188
|
+
notify
|
189
|
+
end
|
174
190
|
end
|
175
191
|
|
192
|
+
# def remove_without_reset
|
193
|
+
# name = child.association_name
|
194
|
+
# @attributes.remove(name, child.raw_attributes)
|
195
|
+
# notify
|
196
|
+
# end
|
197
|
+
|
176
198
|
# Return an array with this +Document+ only in it.
|
177
199
|
def to_a
|
178
200
|
[ self ]
|
data/lib/mongoid/extensions.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "mongoid/extensions/time_conversions"
|
3
3
|
require "mongoid/extensions/array/accessors"
|
4
|
-
require "mongoid/extensions/array/aliasing"
|
5
4
|
require "mongoid/extensions/array/assimilation"
|
6
5
|
require "mongoid/extensions/array/conversions"
|
7
6
|
require "mongoid/extensions/array/parentization"
|
@@ -25,6 +24,7 @@ require "mongoid/extensions/proc/scoping"
|
|
25
24
|
require "mongoid/extensions/string/conversions"
|
26
25
|
require "mongoid/extensions/string/inflections"
|
27
26
|
require "mongoid/extensions/symbol/inflections"
|
27
|
+
require "mongoid/extensions/symbol/conversions"
|
28
28
|
require "mongoid/extensions/true_class/equality"
|
29
29
|
require "mongoid/extensions/objectid/conversions"
|
30
30
|
|
@@ -101,6 +101,7 @@ end
|
|
101
101
|
class Symbol #:nodoc
|
102
102
|
remove_method :size if instance_methods.include? :size # temporal fix for ruby 1.9
|
103
103
|
include Mongoid::Extensions::Symbol::Inflections
|
104
|
+
include Mongoid::Extensions::Symbol::Conversions
|
104
105
|
end
|
105
106
|
|
106
107
|
class Time #:nodoc
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Extensions #:nodoc:
|
4
|
+
module Symbol#:nodoc:
|
5
|
+
# This module converts objects into mongoid related objects.
|
6
|
+
module Conversions #:nodoc:
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def set(value)
|
11
|
+
(value.nil? or (value.respond_to?(:empty?) && value.empty?)) ? nil : value.to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(value)
|
15
|
+
value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/mongoid/finders.rb
CHANGED
@@ -4,8 +4,9 @@ module Mongoid #:nodoc:
|
|
4
4
|
|
5
5
|
# Delegate to the criteria methods that are natural for creating a new
|
6
6
|
# criteria.
|
7
|
-
[ :all_in, :any_in, :
|
8
|
-
:
|
7
|
+
[ :all_in, :any_in, :asc, :ascending, :avg, :desc, :descending,
|
8
|
+
:excludes, :limit, :max, :min, :not_in, :only, :order_by,
|
9
|
+
:skip, :sum, :where, :near ].each do |name|
|
9
10
|
define_method(name) do |*args|
|
10
11
|
criteria.send(name, *args)
|
11
12
|
end
|
data/lib/mongoid/indexes.rb
CHANGED
@@ -3,24 +3,35 @@ module Mongoid #:nodoc
|
|
3
3
|
module Indexes #:nodoc
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
included do
|
6
|
-
cattr_accessor :
|
7
|
-
self.
|
6
|
+
cattr_accessor :index_options
|
7
|
+
self.index_options = {}
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods #:nodoc
|
11
|
+
|
12
|
+
# Send the actual index creation comments to the MongoDB driver
|
13
|
+
def create_indexes
|
14
|
+
return unless index_options
|
15
|
+
|
16
|
+
index_options.each do |name, options|
|
17
|
+
self._collection.create_index(name, options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
11
21
|
# Add the default indexes to the root document if they do not already
|
12
22
|
# exist. Currently this is only _type.
|
13
23
|
def add_indexes
|
14
|
-
if hereditary && !
|
15
|
-
self.
|
16
|
-
self.indexed = true
|
24
|
+
if hereditary && !index_options[:_type]
|
25
|
+
self.index_options[:_type] = {:unique => false, :background => true}
|
17
26
|
end
|
27
|
+
create_indexes if Mongoid.autocreate_indexes
|
18
28
|
end
|
19
29
|
|
20
30
|
# Adds an index on the field specified. Options can be :unique => true or
|
21
31
|
# :unique => false. It will default to the latter.
|
22
32
|
def index(name, options = { :unique => false })
|
23
|
-
|
33
|
+
self.index_options[name] = options
|
34
|
+
create_indexes if Mongoid.autocreate_indexes
|
24
35
|
end
|
25
36
|
end
|
26
37
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Mongoid
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
delegate :info, :debug, :error, :fatal, :unknown, :to => :logger, :allow_nil => true
|
5
|
+
|
6
|
+
def warn(message)
|
7
|
+
logger.warn(message) if logger && logger.respond_to?(:warn)
|
8
|
+
end
|
9
|
+
|
10
|
+
def logger
|
11
|
+
Mongoid.logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
"#<Mongoid::Logger:0x#{object_id.to_s(16)} @logger=#{logger.inspect}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/mongoid/paranoia.rb
CHANGED
@@ -1,18 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
|
-
module Paranoid #:nodoc:
|
4
|
-
# Find deleted documents
|
5
|
-
#
|
6
|
-
# Examples:
|
7
|
-
#
|
8
|
-
# <tt>Person.deleted</tt> # all deleted employees
|
9
|
-
# <tt>Company.first.employees.deleted</tt> # works with a join
|
10
|
-
# <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt> # retrieve by id a deleted person
|
11
|
-
def deleted
|
12
|
-
where(:deleted_at.exists => false)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
3
|
# Include this module to get soft deletion of root level documents.
|
17
4
|
# This will add a deleted_at field to the +Document+, managed automatically.
|
18
5
|
# Potentially incompatible with unique indices. (if collisions with deleted items)
|
@@ -27,7 +14,6 @@ module Mongoid #:nodoc:
|
|
27
14
|
extend ActiveSupport::Concern
|
28
15
|
|
29
16
|
included do
|
30
|
-
Mongoid::Criteria.send(:include, Mongoid::Paranoid)
|
31
17
|
field :deleted_at, :type => Time
|
32
18
|
end
|
33
19
|
|
@@ -101,6 +87,18 @@ module Mongoid #:nodoc:
|
|
101
87
|
def criteria
|
102
88
|
super.where(:deleted_at.exists => false)
|
103
89
|
end
|
90
|
+
|
91
|
+
# Find deleted documents
|
92
|
+
#
|
93
|
+
# Examples:
|
94
|
+
#
|
95
|
+
# <tt>Person.deleted</tt> # all deleted employees
|
96
|
+
# <tt>Company.first.employees.deleted</tt> # works with a join
|
97
|
+
# <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt> # retrieve by id a deleted person
|
98
|
+
def deleted
|
99
|
+
where(:deleted_at.exists => true)
|
100
|
+
end
|
101
|
+
|
104
102
|
end
|
105
103
|
end
|
106
104
|
end
|
@@ -11,10 +11,6 @@ module Mongoid #:nodoc:
|
|
11
11
|
# false
|
12
12
|
# );
|
13
13
|
class RemoveEmbedded < Command
|
14
|
-
# Insert the new document in the database. If the document's parent is a
|
15
|
-
# new record, we will call save on the parent, otherwise we will $push
|
16
|
-
# the document onto the parent.
|
17
|
-
#
|
18
14
|
# Remove the document from the database. If the parent is a new record,
|
19
15
|
# it will get removed in Ruby only. If the parent is not a new record
|
20
16
|
# then either an $unset or $set will occur, depending if it's an
|
@@ -60,7 +60,10 @@ module Mongoid #:nodoc:
|
|
60
60
|
def update
|
61
61
|
updates = @document._updates
|
62
62
|
unless updates.empty?
|
63
|
+
other_pushes = updates.delete(:other)
|
64
|
+
|
63
65
|
@collection.update(@document._selector, updates, @options.merge(:multi => false))
|
66
|
+
@collection.update(@document._selector, { "$pushAll" => other_pushes }, @options.merge(:multi => false)) if other_pushes
|
64
67
|
end; true
|
65
68
|
end
|
66
69
|
end
|
data/lib/mongoid/railtie.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
|
+
require "singleton"
|
1
2
|
require "rails"
|
3
|
+
require "mongoid/config"
|
2
4
|
module Rails #:nodoc:
|
3
5
|
module Mongoid #:nodoc:
|
4
6
|
class Railtie < Rails::Railtie #:nodoc:
|
5
7
|
|
6
|
-
# do we want a custom log subscriber for mongoid?
|
7
|
-
# log_subscriber :mongoid, ::Mongoid::Railties::LogSubscriber.new
|
8
|
-
|
9
8
|
config.generators.orm :mongoid, :migration => false
|
10
9
|
|
11
10
|
rake_tasks do
|
12
11
|
load "mongoid/railties/database.rake"
|
13
12
|
end
|
14
13
|
|
14
|
+
# Exposes Mongoid's configuration to the Rails application configuration.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
#
|
18
|
+
# module MyApplication
|
19
|
+
# class Application < Rails::Application
|
20
|
+
# config.mongoid.logger = Logger.new($stdout, :warn)
|
21
|
+
# config.mongoid.reconnect_time = 10
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
config.mongoid = ::Mongoid::Config.instance
|
25
|
+
|
15
26
|
# Initialize Mongoid. This will look for a mongoid.yml in the config
|
16
27
|
# directory and configure mongoid appropriately.
|
17
28
|
#
|
@@ -51,6 +62,28 @@ module Rails #:nodoc:
|
|
51
62
|
end
|
52
63
|
end
|
53
64
|
end
|
65
|
+
|
66
|
+
initializer "reconnect to master if application is preloaded" do
|
67
|
+
config.after_initialize do
|
68
|
+
# Unicorn clears the START_CTX when a worker is forked, so if we have
|
69
|
+
# data in START_CTX then we know we're being preloaded. Unicorn does
|
70
|
+
# not provide application-level hooks for executing code after the
|
71
|
+
# process has forked, so we reconnect lazily.
|
72
|
+
if defined?(Unicorn) && !Unicorn::HttpServer::START_CTX.empty?
|
73
|
+
::Mongoid.reconnect!(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Passenger provides the :starting_worker_process event for executing
|
77
|
+
# code after it has forked, so we use that and reconnect immediately.
|
78
|
+
if defined?(PhusionPassenger)
|
79
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
80
|
+
if forked
|
81
|
+
::Mongoid.reconnect!
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
54
87
|
end
|
55
88
|
end
|
56
|
-
end
|
89
|
+
end
|