mongoid 2.0.0.beta.9 → 2.0.0.beta.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|