mongoid-rails2 1.9.3
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/MIT_LICENSE +20 -0
- data/README.rdoc +49 -0
- data/lib/mongoid/associations/belongs_to_related.rb +58 -0
- data/lib/mongoid/associations/embedded_in.rb +72 -0
- data/lib/mongoid/associations/embeds_many.rb +254 -0
- data/lib/mongoid/associations/embeds_one.rb +96 -0
- data/lib/mongoid/associations/has_many_related.rb +181 -0
- data/lib/mongoid/associations/has_one_related.rb +85 -0
- data/lib/mongoid/associations/meta_data.rb +29 -0
- data/lib/mongoid/associations/options.rb +57 -0
- data/lib/mongoid/associations/proxy.rb +24 -0
- data/lib/mongoid/associations.rb +300 -0
- data/lib/mongoid/attributes.rb +204 -0
- data/lib/mongoid/callbacks.rb +23 -0
- data/lib/mongoid/collection.rb +120 -0
- data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
- data/lib/mongoid/collections/master.rb +29 -0
- data/lib/mongoid/collections/operations.rb +41 -0
- data/lib/mongoid/collections/slaves.rb +45 -0
- data/lib/mongoid/collections.rb +41 -0
- data/lib/mongoid/components.rb +27 -0
- data/lib/mongoid/concern.rb +31 -0
- data/lib/mongoid/config.rb +191 -0
- data/lib/mongoid/contexts/enumerable.rb +151 -0
- data/lib/mongoid/contexts/ids.rb +25 -0
- data/lib/mongoid/contexts/mongo.rb +285 -0
- data/lib/mongoid/contexts/paging.rb +50 -0
- data/lib/mongoid/contexts.rb +25 -0
- data/lib/mongoid/criteria.rb +249 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +110 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/cursor.rb +81 -0
- data/lib/mongoid/deprecation.rb +22 -0
- data/lib/mongoid/dirty.rb +253 -0
- data/lib/mongoid/document.rb +311 -0
- data/lib/mongoid/errors.rb +108 -0
- data/lib/mongoid/extensions/array/accessors.rb +17 -0
- data/lib/mongoid/extensions/array/aliasing.rb +4 -0
- data/lib/mongoid/extensions/array/assimilation.rb +26 -0
- data/lib/mongoid/extensions/array/conversions.rb +29 -0
- data/lib/mongoid/extensions/array/parentization.rb +13 -0
- data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
- data/lib/mongoid/extensions/binary/conversions.rb +17 -0
- data/lib/mongoid/extensions/boolean/conversions.rb +22 -0
- data/lib/mongoid/extensions/date/conversions.rb +24 -0
- data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
- data/lib/mongoid/extensions/float/conversions.rb +20 -0
- data/lib/mongoid/extensions/hash/accessors.rb +38 -0
- data/lib/mongoid/extensions/hash/assimilation.rb +39 -0
- data/lib/mongoid/extensions/hash/conversions.rb +45 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +21 -0
- data/lib/mongoid/extensions/hash/scoping.rb +12 -0
- data/lib/mongoid/extensions/integer/conversions.rb +20 -0
- data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
- data/lib/mongoid/extensions/object/conversions.rb +33 -0
- data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
- data/lib/mongoid/extensions/proc/scoping.rb +12 -0
- data/lib/mongoid/extensions/string/conversions.rb +15 -0
- data/lib/mongoid/extensions/string/inflections.rb +97 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/extensions/time_conversions.rb +35 -0
- data/lib/mongoid/extensions.rb +101 -0
- data/lib/mongoid/extras.rb +61 -0
- data/lib/mongoid/factory.rb +20 -0
- data/lib/mongoid/field.rb +59 -0
- data/lib/mongoid/fields.rb +65 -0
- data/lib/mongoid/finders.rb +144 -0
- data/lib/mongoid/identity.rb +39 -0
- data/lib/mongoid/indexes.rb +30 -0
- data/lib/mongoid/javascript/functions.yml +37 -0
- data/lib/mongoid/javascript.rb +21 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/lib/mongoid/matchers.rb +36 -0
- data/lib/mongoid/memoization.rb +33 -0
- data/lib/mongoid/named_scope.rb +37 -0
- data/lib/mongoid/observable.rb +30 -0
- data/lib/mongoid/paths.rb +62 -0
- data/lib/mongoid/persistence/command.rb +39 -0
- data/lib/mongoid/persistence/insert.rb +50 -0
- data/lib/mongoid/persistence/insert_embedded.rb +38 -0
- data/lib/mongoid/persistence/remove.rb +39 -0
- data/lib/mongoid/persistence/remove_all.rb +37 -0
- data/lib/mongoid/persistence/remove_embedded.rb +50 -0
- data/lib/mongoid/persistence/update.rb +63 -0
- data/lib/mongoid/persistence.rb +222 -0
- data/lib/mongoid/scope.rb +75 -0
- data/lib/mongoid/state.rb +39 -0
- data/lib/mongoid/timestamps.rb +27 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/mongoid/versioning.rb +27 -0
- data/lib/mongoid.rb +122 -0
- metadata +298 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Attributes
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.class_eval do
|
|
6
|
+
include InstanceMethods
|
|
7
|
+
extend ClassMethods
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
module InstanceMethods
|
|
11
|
+
# Get the id associated with this object. This will pull the _id value out
|
|
12
|
+
# of the attributes +Hash+.
|
|
13
|
+
def id
|
|
14
|
+
@attributes["_id"]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Set the id of the +Document+ to a new one.
|
|
18
|
+
def id=(new_id)
|
|
19
|
+
@attributes["_id"] = new_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
alias :_id :id
|
|
23
|
+
alias :_id= :id=
|
|
24
|
+
|
|
25
|
+
# Used for allowing accessor methods for dynamic attributes.
|
|
26
|
+
def method_missing(name, *args)
|
|
27
|
+
attr = name.to_s
|
|
28
|
+
return super unless @attributes.has_key?(attr.reader)
|
|
29
|
+
if attr.writer?
|
|
30
|
+
# "args.size > 1" allows to simulate 1.8 behavior of "*args"
|
|
31
|
+
@attributes[attr.reader] = (args.size > 1) ? args : args.first
|
|
32
|
+
else
|
|
33
|
+
@attributes[attr.reader]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Process the provided attributes casting them to their proper values if a
|
|
38
|
+
# field exists for them on the +Document+. This will be limited to only the
|
|
39
|
+
# attributes provided in the suppied +Hash+ so that no extra nil values get
|
|
40
|
+
# put into the document's attributes.
|
|
41
|
+
def process(attrs = nil)
|
|
42
|
+
(attrs || {}).each_pair do |key, value|
|
|
43
|
+
if set_allowed?(key)
|
|
44
|
+
@attributes[key.to_s] = value
|
|
45
|
+
elsif write_allowed?(key)
|
|
46
|
+
send("#{key}=", value)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
setup_modifications
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Read a value from the +Document+ attributes. If the value does not exist
|
|
53
|
+
# it will return nil.
|
|
54
|
+
#
|
|
55
|
+
# Options:
|
|
56
|
+
#
|
|
57
|
+
# name: The name of the attribute to get.
|
|
58
|
+
#
|
|
59
|
+
# Example:
|
|
60
|
+
#
|
|
61
|
+
# <tt>person.read_attribute(:title)</tt>
|
|
62
|
+
def read_attribute(name)
|
|
63
|
+
access = name.to_s
|
|
64
|
+
accessed(access, fields[access].get(@attributes[access]))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Remove a value from the +Document+ attributes. If the value does not exist
|
|
68
|
+
# it will fail gracefully.
|
|
69
|
+
#
|
|
70
|
+
# Options:
|
|
71
|
+
#
|
|
72
|
+
# name: The name of the attribute to remove.
|
|
73
|
+
#
|
|
74
|
+
# Example:
|
|
75
|
+
#
|
|
76
|
+
# <tt>person.remove_attribute(:title)</tt>
|
|
77
|
+
def remove_attribute(name)
|
|
78
|
+
access = name.to_s
|
|
79
|
+
modify(access, @attributes.delete(access), nil)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns the object type. This corresponds to the name of the class that
|
|
83
|
+
# this +Document+ is, which is used in determining the class to
|
|
84
|
+
# instantiate in various cases.
|
|
85
|
+
def _type
|
|
86
|
+
@attributes["_type"]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Set the type of the +Document+. This should be the name of the class.
|
|
90
|
+
def _type=(new_type)
|
|
91
|
+
@attributes["_type"] = new_type
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Write a single attribute to the +Document+ attribute +Hash+. This will
|
|
95
|
+
# also fire the before and after update callbacks, and perform any
|
|
96
|
+
# necessary typecasting.
|
|
97
|
+
#
|
|
98
|
+
# Options:
|
|
99
|
+
#
|
|
100
|
+
# name: The name of the attribute to update.
|
|
101
|
+
# value: The value to set for the attribute.
|
|
102
|
+
#
|
|
103
|
+
# Example:
|
|
104
|
+
#
|
|
105
|
+
# <tt>person.write_attribute(:title, "Mr.")</tt>
|
|
106
|
+
#
|
|
107
|
+
# This will also cause the observing +Document+ to notify it's parent if
|
|
108
|
+
# there is any.
|
|
109
|
+
def write_attribute(name, value)
|
|
110
|
+
access = name.to_s
|
|
111
|
+
modify(access, @attributes[access], fields[access].set(value))
|
|
112
|
+
notify if !id.blank? && new_record?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Writes the supplied attributes +Hash+ to the +Document+. This will only
|
|
116
|
+
# overwrite existing attributes if they are present in the new +Hash+, all
|
|
117
|
+
# others will be preserved.
|
|
118
|
+
#
|
|
119
|
+
# Options:
|
|
120
|
+
#
|
|
121
|
+
# attrs: The +Hash+ of new attributes to set on the +Document+
|
|
122
|
+
#
|
|
123
|
+
# Example:
|
|
124
|
+
#
|
|
125
|
+
# <tt>person.write_attributes(:title => "Mr.")</tt>
|
|
126
|
+
#
|
|
127
|
+
# This will also cause the observing +Document+ to notify it's parent if
|
|
128
|
+
# there is any.
|
|
129
|
+
def write_attributes(attrs = nil)
|
|
130
|
+
process(attrs || {})
|
|
131
|
+
identified = !id.blank?
|
|
132
|
+
if new_record? && !identified
|
|
133
|
+
identify; notify
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
alias :attributes= write_attributes
|
|
137
|
+
|
|
138
|
+
protected
|
|
139
|
+
# apply default values to attributes - calling procs as required
|
|
140
|
+
def default_attributes
|
|
141
|
+
default_values = defaults
|
|
142
|
+
default_values.each_pair do |key, val|
|
|
143
|
+
default_values[key] = val.call if val.respond_to?(:call)
|
|
144
|
+
end
|
|
145
|
+
default_values || {}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Return true if dynamic field setting is enabled.
|
|
149
|
+
def set_allowed?(key)
|
|
150
|
+
Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Used when supplying a :reject_if block as an option to
|
|
154
|
+
# accepts_nested_attributes_for
|
|
155
|
+
def reject(attributes, options)
|
|
156
|
+
rejector = options[:reject_if]
|
|
157
|
+
if rejector
|
|
158
|
+
attributes.delete_if do |key, value|
|
|
159
|
+
rejector.call(value)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Return true if writing to the given field is allowed
|
|
165
|
+
def write_allowed?(key)
|
|
166
|
+
name = key.to_s
|
|
167
|
+
existing = fields[name]
|
|
168
|
+
return true unless existing
|
|
169
|
+
existing.accessible?
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
module ClassMethods
|
|
174
|
+
# Defines attribute setters for the associations specified by the names.
|
|
175
|
+
# This will work for a has one or has many association.
|
|
176
|
+
#
|
|
177
|
+
# Example:
|
|
178
|
+
#
|
|
179
|
+
# class Person
|
|
180
|
+
# include Mongoid::Document
|
|
181
|
+
# embeds_one :name
|
|
182
|
+
# embeds_many :addresses
|
|
183
|
+
#
|
|
184
|
+
# accepts_nested_attributes_for :name, :addresses
|
|
185
|
+
# end
|
|
186
|
+
def accepts_nested_attributes_for(*args)
|
|
187
|
+
associations = args.flatten
|
|
188
|
+
options = associations.last.is_a?(Hash) ? associations.pop : {}
|
|
189
|
+
associations.each do |name|
|
|
190
|
+
define_method("#{name}_attributes=") do |attrs|
|
|
191
|
+
reject(attrs, options)
|
|
192
|
+
association = send(name)
|
|
193
|
+
if association
|
|
194
|
+
observe(association, true)
|
|
195
|
+
association.nested_build(attrs)
|
|
196
|
+
else
|
|
197
|
+
send("build_#{name}", attrs)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Callbacks
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.class_eval do
|
|
6
|
+
include ActiveSupport::Callbacks
|
|
7
|
+
|
|
8
|
+
# Define all the callbacks that are accepted by the document.
|
|
9
|
+
define_callbacks \
|
|
10
|
+
:before_create,
|
|
11
|
+
:after_create,
|
|
12
|
+
:before_destroy,
|
|
13
|
+
:after_destroy,
|
|
14
|
+
:before_save,
|
|
15
|
+
:after_save,
|
|
16
|
+
:before_update,
|
|
17
|
+
:after_update,
|
|
18
|
+
:before_validation,
|
|
19
|
+
:after_validation
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "mongoid/collections/operations"
|
|
3
|
+
require "mongoid/collections/cyclic_iterator"
|
|
4
|
+
require "mongoid/collections/master"
|
|
5
|
+
require "mongoid/collections/slaves"
|
|
6
|
+
|
|
7
|
+
module Mongoid #:nodoc
|
|
8
|
+
# The Mongoid wrapper to the Mongo Ruby driver's collection object.
|
|
9
|
+
class Collection
|
|
10
|
+
attr_reader :counter, :name
|
|
11
|
+
|
|
12
|
+
# All write operations should delegate to the master connection. These
|
|
13
|
+
# operations mimic the methods on a Mongo:Collection.
|
|
14
|
+
#
|
|
15
|
+
# Example:
|
|
16
|
+
#
|
|
17
|
+
# <tt>collection.save({ :name => "Al" })</tt>
|
|
18
|
+
Collections::Operations::PROXIED.each do |name|
|
|
19
|
+
define_method(name) { |*args| master.send(name, *args) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Determines where to send the next read query. If the slaves are not
|
|
23
|
+
# defined then send to master. If the read counter is under the configured
|
|
24
|
+
# maximum then return the master. In any other case return the slaves.
|
|
25
|
+
#
|
|
26
|
+
# Example:
|
|
27
|
+
#
|
|
28
|
+
# <tt>collection.directed</tt>
|
|
29
|
+
#
|
|
30
|
+
# Return:
|
|
31
|
+
#
|
|
32
|
+
# Either a +Master+ or +Slaves+ collection.
|
|
33
|
+
def directed(options = {})
|
|
34
|
+
options.delete(:cache)
|
|
35
|
+
enslave = options.delete(:enslave) || @klass.enslaved?
|
|
36
|
+
enslave ? master_or_slaves : master
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Find documents from the database given a selector and options.
|
|
40
|
+
#
|
|
41
|
+
# Options:
|
|
42
|
+
#
|
|
43
|
+
# selector: A +Hash+ selector that is the query.
|
|
44
|
+
# options: The options to pass to the db.
|
|
45
|
+
#
|
|
46
|
+
# Example:
|
|
47
|
+
#
|
|
48
|
+
# <tt>collection.find({ :test => "value" })</tt>
|
|
49
|
+
def find(selector = {}, options = {})
|
|
50
|
+
cursor = Mongoid::Cursor.new(@klass, self, directed(options).find(selector, options))
|
|
51
|
+
if block_given?
|
|
52
|
+
yield cursor; cursor.close
|
|
53
|
+
else
|
|
54
|
+
cursor
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Find the first document from the database given a selector and options.
|
|
59
|
+
#
|
|
60
|
+
# Options:
|
|
61
|
+
#
|
|
62
|
+
# selector: A +Hash+ selector that is the query.
|
|
63
|
+
# options: The options to pass to the db.
|
|
64
|
+
#
|
|
65
|
+
# Example:
|
|
66
|
+
#
|
|
67
|
+
# <tt>collection.find_one({ :test => "value" })</tt>
|
|
68
|
+
def find_one(selector = {}, options = {})
|
|
69
|
+
directed(options).find_one(selector, options)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Initialize a new Mongoid::Collection, setting up the master, slave, and
|
|
73
|
+
# name attributes. Masters will be used for writes, slaves for reads.
|
|
74
|
+
#
|
|
75
|
+
# Example:
|
|
76
|
+
#
|
|
77
|
+
# <tt>Mongoid::Collection.new(masters, slaves, "test")</tt>
|
|
78
|
+
def initialize(klass, name)
|
|
79
|
+
@klass, @name = klass, name
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Perform a map/reduce on the documents.
|
|
83
|
+
#
|
|
84
|
+
# Options:
|
|
85
|
+
#
|
|
86
|
+
# map: The map javascript funcdtion.
|
|
87
|
+
# reduce: The reduce javascript function.
|
|
88
|
+
def map_reduce(map, reduce, options = {})
|
|
89
|
+
directed(options).map_reduce(map, reduce, options)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
alias :mapreduce :map_reduce
|
|
93
|
+
|
|
94
|
+
# Return the object responsible for writes to the database. This will
|
|
95
|
+
# always return a collection associated with the Master DB.
|
|
96
|
+
#
|
|
97
|
+
# Example:
|
|
98
|
+
#
|
|
99
|
+
# <tt>collection.writer</tt>
|
|
100
|
+
def master
|
|
101
|
+
@master ||= Collections::Master.new(Mongoid.master, @name)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Return the object responsible for reading documents from the database.
|
|
105
|
+
# This is usually the slave databases, but in their absence the master will
|
|
106
|
+
# handle the task.
|
|
107
|
+
#
|
|
108
|
+
# Example:
|
|
109
|
+
#
|
|
110
|
+
# <tt>collection.reader</tt>
|
|
111
|
+
def slaves
|
|
112
|
+
@slaves ||= Collections::Slaves.new(Mongoid.slaves, @name)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
protected
|
|
116
|
+
def master_or_slaves
|
|
117
|
+
slaves.empty? ? master : slaves
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Collections #:nodoc:
|
|
4
|
+
class CyclicIterator
|
|
5
|
+
|
|
6
|
+
attr_reader :counter
|
|
7
|
+
|
|
8
|
+
# Performs iteration over an array, if the array gets to the end then loop
|
|
9
|
+
# back to the first.
|
|
10
|
+
#
|
|
11
|
+
# Example:
|
|
12
|
+
#
|
|
13
|
+
# <tt>CyclicIterator.new([ first, second ])</tt>
|
|
14
|
+
def initialize(array)
|
|
15
|
+
@array, @counter = array, -1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Get the next element in the array. If the element is the last in the
|
|
19
|
+
# array then return the first.
|
|
20
|
+
#
|
|
21
|
+
# Example:
|
|
22
|
+
#
|
|
23
|
+
# <tt>iterator.next</tt>
|
|
24
|
+
#
|
|
25
|
+
# Returns:
|
|
26
|
+
#
|
|
27
|
+
# The next element in the array.
|
|
28
|
+
def next
|
|
29
|
+
(@counter == @array.size - 1) ? @counter = 0 : @counter = @counter + 1
|
|
30
|
+
@array[@counter]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Collections #:nodoc:
|
|
4
|
+
class Master
|
|
5
|
+
|
|
6
|
+
attr_reader :collection
|
|
7
|
+
|
|
8
|
+
# All read and write operations should delegate to the master connection.
|
|
9
|
+
# These operations mimic the methods on a Mongo:Collection.
|
|
10
|
+
#
|
|
11
|
+
# Example:
|
|
12
|
+
#
|
|
13
|
+
# <tt>collection.save({ :name => "Al" })</tt>
|
|
14
|
+
Operations::ALL.each do |name|
|
|
15
|
+
define_method(name) { |*args| collection.send(name, *args) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Create the new database writer. Will create a collection from the
|
|
19
|
+
# master database.
|
|
20
|
+
#
|
|
21
|
+
# Example:
|
|
22
|
+
#
|
|
23
|
+
# <tt>Master.new(master, "mongoid_people")</tt>
|
|
24
|
+
def initialize(master, name)
|
|
25
|
+
@collection = master.collection(name)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Collections #:nodoc:
|
|
4
|
+
module Operations #:nodoc:
|
|
5
|
+
# Constant definining all the read operations available for a
|
|
6
|
+
# Mongo:Collection. This is used in delegation.
|
|
7
|
+
READ = [
|
|
8
|
+
:[],
|
|
9
|
+
:db,
|
|
10
|
+
:count,
|
|
11
|
+
:distinct,
|
|
12
|
+
:find,
|
|
13
|
+
:find_one,
|
|
14
|
+
:group,
|
|
15
|
+
:index_information,
|
|
16
|
+
:map_reduce,
|
|
17
|
+
:mapreduce,
|
|
18
|
+
:options
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
# Constant definining all the write operations available for a
|
|
22
|
+
# Mongo:Collection. This is used in delegation.
|
|
23
|
+
WRITE = [
|
|
24
|
+
:<<,
|
|
25
|
+
:create_index,
|
|
26
|
+
:drop,
|
|
27
|
+
:drop_index,
|
|
28
|
+
:drop_indexes,
|
|
29
|
+
:insert,
|
|
30
|
+
:remove,
|
|
31
|
+
:rename,
|
|
32
|
+
:save,
|
|
33
|
+
:update
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
# Convenience constant for getting back all collection operations.
|
|
37
|
+
ALL = (READ + WRITE)
|
|
38
|
+
PROXIED = ALL - [ :find, :find_one, :map_reduce, :mapreduce ]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Collections #:nodoc:
|
|
4
|
+
class Slaves
|
|
5
|
+
|
|
6
|
+
attr_reader :iterator
|
|
7
|
+
|
|
8
|
+
# All read operations should delegate to the slave connections.
|
|
9
|
+
# These operations mimic the methods on a Mongo:Collection.
|
|
10
|
+
#
|
|
11
|
+
# Example:
|
|
12
|
+
#
|
|
13
|
+
# <tt>collection.save({ :name => "Al" })</tt>
|
|
14
|
+
Operations::READ.each do |name|
|
|
15
|
+
define_method(name) { |*args| collection.send(name, *args) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Is the collection of slaves empty or not?
|
|
19
|
+
#
|
|
20
|
+
# Return:
|
|
21
|
+
#
|
|
22
|
+
# True is the iterator is not set, false if not.
|
|
23
|
+
def empty?
|
|
24
|
+
@iterator.nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Create the new database reader. Will create a collection from the
|
|
28
|
+
# slave databases and cycle through them on each read.
|
|
29
|
+
#
|
|
30
|
+
# Example:
|
|
31
|
+
#
|
|
32
|
+
# <tt>Reader.new(slaves, "mongoid_people")</tt>
|
|
33
|
+
def initialize(slaves, name)
|
|
34
|
+
unless slaves.blank?
|
|
35
|
+
@iterator = CyclicIterator.new(slaves.collect { |db| db.collection(name) })
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
protected
|
|
40
|
+
def collection
|
|
41
|
+
@iterator.next
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc
|
|
3
|
+
# The collections module is used for providing functionality around setting
|
|
4
|
+
# up and updating collections.
|
|
5
|
+
module Collections
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
included do
|
|
8
|
+
cattr_accessor :_collection, :collection_name
|
|
9
|
+
self.collection_name = self.name.collectionize
|
|
10
|
+
delegate :collection, :to => "self.class"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods #:nodoc:
|
|
14
|
+
# Returns the collection associated with this +Document+. If the
|
|
15
|
+
# document is embedded, there will be no collection associated
|
|
16
|
+
# with it.
|
|
17
|
+
#
|
|
18
|
+
# Returns: <tt>Mongo::Collection</tt>
|
|
19
|
+
def collection
|
|
20
|
+
raise Errors::InvalidCollection.new(self) if embedded?
|
|
21
|
+
self._collection || set_collection
|
|
22
|
+
add_indexes; self._collection
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Macro for setting the collection name to store in.
|
|
26
|
+
#
|
|
27
|
+
# Example:
|
|
28
|
+
#
|
|
29
|
+
# <tt>Person.store_in :populdation</tt>
|
|
30
|
+
def store_in(name)
|
|
31
|
+
self.collection_name = name.to_s
|
|
32
|
+
set_collection
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
protected
|
|
36
|
+
def set_collection
|
|
37
|
+
self._collection = Mongoid::Collection.new(self, self.collection_name)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc
|
|
3
|
+
module Components #:nodoc
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
included do
|
|
6
|
+
# All modules that a +Document+ is composed of are defined in this
|
|
7
|
+
# module, to keep the document class from getting too cluttered.
|
|
8
|
+
include Mongoid::Associations
|
|
9
|
+
include Mongoid::Attributes
|
|
10
|
+
include Mongoid::Callbacks
|
|
11
|
+
include Mongoid::Collections
|
|
12
|
+
include Mongoid::Dirty
|
|
13
|
+
include Mongoid::Extras
|
|
14
|
+
include Mongoid::Fields
|
|
15
|
+
include Mongoid::Indexes
|
|
16
|
+
include Mongoid::Matchers
|
|
17
|
+
include Mongoid::Memoization
|
|
18
|
+
include Mongoid::Observable
|
|
19
|
+
include Mongoid::Paths
|
|
20
|
+
include Mongoid::Persistence
|
|
21
|
+
include Mongoid::State
|
|
22
|
+
include Validatable
|
|
23
|
+
extend Mongoid::Finders
|
|
24
|
+
extend Mongoid::NamedScope
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
unless defined?(ActiveSupport::Concern)
|
|
2
|
+
module ActiveSupport
|
|
3
|
+
module Concern
|
|
4
|
+
def self.extended(base)
|
|
5
|
+
base.instance_variable_set("@_dependencies", [])
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def append_features(base)
|
|
9
|
+
if base.instance_variable_defined?("@_dependencies")
|
|
10
|
+
base.instance_variable_get("@_dependencies") << self
|
|
11
|
+
return false
|
|
12
|
+
else
|
|
13
|
+
return false if base < self
|
|
14
|
+
@_dependencies.each { |dep| base.send(:include, dep) }
|
|
15
|
+
super
|
|
16
|
+
base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
|
|
17
|
+
base.send :include, const_get("InstanceMethods") if const_defined?("InstanceMethods")
|
|
18
|
+
base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def included(base = nil, &block)
|
|
23
|
+
if base.nil?
|
|
24
|
+
@_included_block = block
|
|
25
|
+
else
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|