mongoid-pre 2.0.0.beta1
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/.gitignore +6 -0
- data/.watchr +24 -0
- data/MIT_LICENSE +20 -0
- data/README.rdoc +49 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/caliper.yml +4 -0
- data/lib/mongoid.rb +135 -0
- data/lib/mongoid/associations.rb +263 -0
- data/lib/mongoid/associations/belongs_to_related.rb +59 -0
- data/lib/mongoid/associations/embedded_in.rb +64 -0
- data/lib/mongoid/associations/embeds_many.rb +193 -0
- data/lib/mongoid/associations/embeds_one.rb +95 -0
- data/lib/mongoid/associations/has_many_related.rb +133 -0
- data/lib/mongoid/associations/has_one_related.rb +81 -0
- data/lib/mongoid/associations/meta_data.rb +28 -0
- data/lib/mongoid/associations/options.rb +52 -0
- data/lib/mongoid/associations/proxy.rb +31 -0
- data/lib/mongoid/attributes.rb +185 -0
- data/lib/mongoid/callbacks.rb +18 -0
- data/lib/mongoid/collection.rb +119 -0
- data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
- data/lib/mongoid/collections/master.rb +28 -0
- data/lib/mongoid/collections/mimic.rb +46 -0
- data/lib/mongoid/collections/operations.rb +41 -0
- data/lib/mongoid/collections/slaves.rb +44 -0
- data/lib/mongoid/commands.rb +161 -0
- data/lib/mongoid/commands/create.rb +19 -0
- data/lib/mongoid/commands/delete.rb +16 -0
- data/lib/mongoid/commands/delete_all.rb +25 -0
- data/lib/mongoid/commands/deletion.rb +18 -0
- data/lib/mongoid/commands/destroy.rb +17 -0
- data/lib/mongoid/commands/destroy_all.rb +25 -0
- data/lib/mongoid/commands/save.rb +30 -0
- data/lib/mongoid/components.rb +31 -0
- data/lib/mongoid/config.rb +86 -0
- data/lib/mongoid/contexts.rb +25 -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 +42 -0
- data/lib/mongoid/criteria.rb +239 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +93 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/cursor.rb +82 -0
- data/lib/mongoid/deprecation.rb +22 -0
- data/lib/mongoid/dirty.rb +203 -0
- data/lib/mongoid/document.rb +306 -0
- data/lib/mongoid/errors.rb +77 -0
- data/lib/mongoid/extensions.rb +99 -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 +27 -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 +16 -0
- data/lib/mongoid/extensions/date/conversions.rb +15 -0
- data/lib/mongoid/extensions/datetime/conversions.rb +17 -0
- data/lib/mongoid/extensions/float/conversions.rb +16 -0
- data/lib/mongoid/extensions/hash/accessors.rb +38 -0
- data/lib/mongoid/extensions/hash/assimilation.rb +30 -0
- data/lib/mongoid/extensions/hash/conversions.rb +15 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/hash/scoping.rb +12 -0
- data/lib/mongoid/extensions/integer/conversions.rb +16 -0
- data/lib/mongoid/extensions/nil/assimilation.rb +13 -0
- data/lib/mongoid/extensions/object/conversions.rb +27 -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 +18 -0
- data/lib/mongoid/extras.rb +61 -0
- data/lib/mongoid/factory.rb +19 -0
- data/lib/mongoid/field.rb +52 -0
- data/lib/mongoid/fields.rb +62 -0
- data/lib/mongoid/finders.rb +136 -0
- data/lib/mongoid/identity.rb +39 -0
- data/lib/mongoid/indexes.rb +27 -0
- data/lib/mongoid/javascript.rb +21 -0
- data/lib/mongoid/javascript/functions.yml +37 -0
- data/lib/mongoid/matchers.rb +36 -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/memoization.rb +27 -0
- data/lib/mongoid/named_scope.rb +42 -0
- data/lib/mongoid/observable.rb +30 -0
- data/lib/mongoid/paths.rb +54 -0
- data/lib/mongoid/persistence.rb +27 -0
- data/lib/mongoid/persistence/command.rb +20 -0
- data/lib/mongoid/persistence/insert.rb +71 -0
- data/lib/mongoid/persistence/update.rb +78 -0
- data/lib/mongoid/scope.rb +75 -0
- data/lib/mongoid/state.rb +32 -0
- data/lib/mongoid/timestamps.rb +27 -0
- data/lib/mongoid/validations.rb +51 -0
- data/lib/mongoid/validations/associated.rb +32 -0
- data/lib/mongoid/validations/locale/en.yml +4 -0
- data/lib/mongoid/validations/uniqueness.rb +22 -0
- data/lib/mongoid/versioning.rb +26 -0
- data/mongoid.gemspec +413 -0
- data/perf/benchmark.rb +77 -0
- data/spec/integration/mongoid/associations_spec.rb +340 -0
- data/spec/integration/mongoid/attributes_spec.rb +22 -0
- data/spec/integration/mongoid/commands_spec.rb +230 -0
- data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
- data/spec/integration/mongoid/criteria_spec.rb +272 -0
- data/spec/integration/mongoid/dirty_spec.rb +70 -0
- data/spec/integration/mongoid/document_spec.rb +650 -0
- data/spec/integration/mongoid/extensions_spec.rb +22 -0
- data/spec/integration/mongoid/finders_spec.rb +119 -0
- data/spec/integration/mongoid/inheritance_spec.rb +137 -0
- data/spec/integration/mongoid/named_scope_spec.rb +46 -0
- data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
- data/spec/models/address.rb +39 -0
- data/spec/models/animal.rb +6 -0
- data/spec/models/callbacks.rb +18 -0
- data/spec/models/comment.rb +8 -0
- data/spec/models/country_code.rb +6 -0
- data/spec/models/employer.rb +5 -0
- data/spec/models/game.rb +7 -0
- data/spec/models/inheritance.rb +56 -0
- data/spec/models/location.rb +5 -0
- data/spec/models/mixed_drink.rb +4 -0
- data/spec/models/name.rb +13 -0
- data/spec/models/namespacing.rb +11 -0
- data/spec/models/patient.rb +6 -0
- data/spec/models/person.rb +99 -0
- data/spec/models/pet.rb +7 -0
- data/spec/models/pet_owner.rb +6 -0
- data/spec/models/phone.rb +7 -0
- data/spec/models/post.rb +15 -0
- data/spec/models/translation.rb +5 -0
- data/spec/models/vet_visit.rb +5 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +145 -0
- data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
- data/spec/unit/mongoid/associations/embeds_many_spec.rb +516 -0
- data/spec/unit/mongoid/associations/embeds_one_spec.rb +282 -0
- data/spec/unit/mongoid/associations/has_many_related_spec.rb +418 -0
- data/spec/unit/mongoid/associations/has_one_related_spec.rb +179 -0
- data/spec/unit/mongoid/associations/meta_data_spec.rb +88 -0
- data/spec/unit/mongoid/associations/options_spec.rb +192 -0
- data/spec/unit/mongoid/associations_spec.rb +595 -0
- data/spec/unit/mongoid/attributes_spec.rb +507 -0
- data/spec/unit/mongoid/callbacks_spec.rb +55 -0
- data/spec/unit/mongoid/collection_spec.rb +187 -0
- data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
- data/spec/unit/mongoid/collections/master_spec.rb +41 -0
- data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
- data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
- data/spec/unit/mongoid/commands/create_spec.rb +31 -0
- data/spec/unit/mongoid/commands/delete_all_spec.rb +59 -0
- data/spec/unit/mongoid/commands/delete_spec.rb +38 -0
- data/spec/unit/mongoid/commands/destroy_all_spec.rb +21 -0
- data/spec/unit/mongoid/commands/destroy_spec.rb +51 -0
- data/spec/unit/mongoid/commands/save_spec.rb +107 -0
- data/spec/unit/mongoid/commands_spec.rb +270 -0
- data/spec/unit/mongoid/config_spec.rb +176 -0
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +421 -0
- data/spec/unit/mongoid/contexts/mongo_spec.rb +682 -0
- data/spec/unit/mongoid/contexts_spec.rb +25 -0
- data/spec/unit/mongoid/criteria_spec.rb +824 -0
- data/spec/unit/mongoid/criterion/complex_spec.rb +19 -0
- data/spec/unit/mongoid/criterion/exclusion_spec.rb +91 -0
- data/spec/unit/mongoid/criterion/inclusion_spec.rb +219 -0
- data/spec/unit/mongoid/criterion/optional_spec.rb +319 -0
- data/spec/unit/mongoid/cursor_spec.rb +74 -0
- data/spec/unit/mongoid/deprecation_spec.rb +24 -0
- data/spec/unit/mongoid/dirty_spec.rb +286 -0
- data/spec/unit/mongoid/document_spec.rb +818 -0
- data/spec/unit/mongoid/errors_spec.rb +103 -0
- data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
- data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
- data/spec/unit/mongoid/extensions/array/conversions_spec.rb +35 -0
- data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
- data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
- data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
- data/spec/unit/mongoid/extensions/date/conversions_spec.rb +102 -0
- data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +67 -0
- data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
- data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +46 -0
- data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +21 -0
- data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
- data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
- data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +24 -0
- data/spec/unit/mongoid/extensions/object/conversions_spec.rb +57 -0
- data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
- data/spec/unit/mongoid/extensions/string/conversions_spec.rb +17 -0
- data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
- data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +91 -0
- data/spec/unit/mongoid/extensions/time/conversions_spec.rb +70 -0
- data/spec/unit/mongoid/extras_spec.rb +102 -0
- data/spec/unit/mongoid/factory_spec.rb +31 -0
- data/spec/unit/mongoid/field_spec.rb +143 -0
- data/spec/unit/mongoid/fields_spec.rb +181 -0
- data/spec/unit/mongoid/finders_spec.rb +404 -0
- data/spec/unit/mongoid/identity_spec.rb +109 -0
- data/spec/unit/mongoid/indexes_spec.rb +93 -0
- data/spec/unit/mongoid/javascript_spec.rb +48 -0
- data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
- data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
- data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
- data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
- data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
- data/spec/unit/mongoid/matchers_spec.rb +329 -0
- data/spec/unit/mongoid/memoization_spec.rb +75 -0
- data/spec/unit/mongoid/named_scope_spec.rb +123 -0
- data/spec/unit/mongoid/observable_spec.rb +46 -0
- data/spec/unit/mongoid/paths_spec.rb +124 -0
- data/spec/unit/mongoid/persistence/insert_spec.rb +175 -0
- data/spec/unit/mongoid/persistence/update_spec.rb +148 -0
- data/spec/unit/mongoid/persistence_spec.rb +40 -0
- data/spec/unit/mongoid/scope_spec.rb +240 -0
- data/spec/unit/mongoid/state_spec.rb +83 -0
- data/spec/unit/mongoid/timestamps_spec.rb +25 -0
- data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
- data/spec/unit/mongoid/validations/uniqueness_spec.rb +47 -0
- data/spec/unit/mongoid/validations_spec.rb +190 -0
- data/spec/unit/mongoid/versioning_spec.rb +41 -0
- data/spec/unit/mongoid_spec.rb +46 -0
- metadata +476 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
class HasOneRelated #:nodoc:
|
|
5
|
+
include Proxy
|
|
6
|
+
|
|
7
|
+
delegate :nil?, :to => :target
|
|
8
|
+
|
|
9
|
+
# Builds a new Document and sets it as the association.
|
|
10
|
+
#
|
|
11
|
+
# Returns the newly created object.
|
|
12
|
+
def build(attributes = {})
|
|
13
|
+
@target = @klass.instantiate(attributes)
|
|
14
|
+
name = @parent.class.to_s.underscore
|
|
15
|
+
@target.send("#{name}=", @parent)
|
|
16
|
+
@target
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Builds a new Document and sets it as the association, then saves the
|
|
20
|
+
# newly created document.
|
|
21
|
+
#
|
|
22
|
+
# Returns the newly created object.
|
|
23
|
+
def create(attributes)
|
|
24
|
+
build(attributes); @target.save; @target
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Initializing a related association only requires looking up the objects
|
|
28
|
+
# by their ids.
|
|
29
|
+
#
|
|
30
|
+
# Options:
|
|
31
|
+
#
|
|
32
|
+
# document: The +Document+ that contains the relationship.
|
|
33
|
+
# options: The association +Options+.
|
|
34
|
+
def initialize(document, options, target = nil)
|
|
35
|
+
@parent, @klass = document, options.klass
|
|
36
|
+
@foreign_key = document.class.to_s.foreign_key
|
|
37
|
+
@target = target || @klass.first(:conditions => { @foreign_key => @parent.id })
|
|
38
|
+
extends(options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
# Preferred method for creating the new +RelatesToMany+ association.
|
|
43
|
+
#
|
|
44
|
+
# Options:
|
|
45
|
+
#
|
|
46
|
+
# document: The +Document+ that contains the relationship.
|
|
47
|
+
# options: The association +Options+.
|
|
48
|
+
def instantiate(document, options, target = nil)
|
|
49
|
+
new(document, options, target)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns the macro used to create the association.
|
|
53
|
+
def macro
|
|
54
|
+
:has_one_related
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Perform an update of the relationship of the parent and child. This
|
|
58
|
+
# will assimilate the child +Document+ into the parent's object graph.
|
|
59
|
+
#
|
|
60
|
+
# Options:
|
|
61
|
+
#
|
|
62
|
+
# related: The related object to update.
|
|
63
|
+
# document: The parent +Document+.
|
|
64
|
+
# options: The association +Options+
|
|
65
|
+
#
|
|
66
|
+
# Example:
|
|
67
|
+
#
|
|
68
|
+
# <tt>HasOneToRelated.update(game, person, options)</tt>
|
|
69
|
+
def update(target, document, options)
|
|
70
|
+
if target
|
|
71
|
+
name = document.class.to_s.underscore
|
|
72
|
+
target.send("#{name}=", document)
|
|
73
|
+
return instantiate(document, options, target)
|
|
74
|
+
end
|
|
75
|
+
target
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
class MetaData #:nodoc:
|
|
5
|
+
|
|
6
|
+
attr_reader :association, :options
|
|
7
|
+
|
|
8
|
+
delegate :macro, :to => :association
|
|
9
|
+
|
|
10
|
+
# Delegate all methods on +Options+ to the options instance.
|
|
11
|
+
Associations::Options.public_instance_methods(false).each do |name|
|
|
12
|
+
define_method(name) { |*args| @options.send(name) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Create the new associations MetaData object, which holds the type of
|
|
16
|
+
# the association and its options, with convenience methods for getting
|
|
17
|
+
# that information.
|
|
18
|
+
#
|
|
19
|
+
# Options:
|
|
20
|
+
#
|
|
21
|
+
# association: The association type as a class instance.
|
|
22
|
+
# options: The association options
|
|
23
|
+
def initialize(association, options)
|
|
24
|
+
@association, @options = association, options
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Associations #:nodoc:
|
|
4
|
+
class Options #:nodoc:
|
|
5
|
+
|
|
6
|
+
# Create the new +Options+ object, which provides convenience methods for
|
|
7
|
+
# accessing values out of an options +Hash+.
|
|
8
|
+
def initialize(attributes = {})
|
|
9
|
+
@attributes = attributes
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Returns the extension if it exists, nil if not.
|
|
13
|
+
def extension
|
|
14
|
+
@attributes[:extend]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns true is the options have extensions.
|
|
18
|
+
def extension?
|
|
19
|
+
!extension.nil?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Return the foreign key based off the association name.
|
|
23
|
+
def foreign_key
|
|
24
|
+
@attributes[:foreign_key] || klass.name.to_s.foreign_key
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns the name of the inverse_of association
|
|
28
|
+
def inverse_of
|
|
29
|
+
@attributes[:inverse_of]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Return a +Class+ for the options. If a class_name was provided, then the
|
|
33
|
+
# constantized class_name will be returned. If not, a constant based on the
|
|
34
|
+
# association name will be returned.
|
|
35
|
+
def klass
|
|
36
|
+
class_name = @attributes[:class_name]
|
|
37
|
+
class_name ? class_name.constantize : name.to_s.classify.constantize
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns the association name of the options.
|
|
41
|
+
def name
|
|
42
|
+
@attributes[:name].to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns whether or not this association is polymorphic.
|
|
46
|
+
def polymorphic
|
|
47
|
+
@attributes[:polymorphic] == true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc
|
|
3
|
+
module Associations #:nodoc
|
|
4
|
+
module Proxy #:nodoc
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.class_eval do
|
|
7
|
+
instance_methods.each do |method|
|
|
8
|
+
undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
|
|
9
|
+
end
|
|
10
|
+
include InstanceMethods
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
module InstanceMethods #:nodoc:
|
|
14
|
+
attr_reader \
|
|
15
|
+
:options,
|
|
16
|
+
:target
|
|
17
|
+
|
|
18
|
+
# Default behavior of method missing should be to delegate all calls
|
|
19
|
+
# to the target of the proxy. This can be overridden in special cases.
|
|
20
|
+
def method_missing(name, *args, &block)
|
|
21
|
+
@target.send(name, *args, &block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# If anonymous extensions are added this will take care of them.
|
|
25
|
+
def extends(options)
|
|
26
|
+
extend Module.new(&options.extension) if options.extension?
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Attributes
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
module InstanceMethods
|
|
6
|
+
# Get the id associated with this object. This will pull the _id value out
|
|
7
|
+
# of the attributes +Hash+.
|
|
8
|
+
def id
|
|
9
|
+
@attributes["_id"]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Set the id of the +Document+ to a new one.
|
|
13
|
+
def id=(new_id)
|
|
14
|
+
@attributes["_id"] = new_id
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
alias :_id :id
|
|
18
|
+
alias :_id= :id=
|
|
19
|
+
|
|
20
|
+
# Used for allowing accessor methods for dynamic attributes.
|
|
21
|
+
def method_missing(name, *args)
|
|
22
|
+
attr = name.to_s
|
|
23
|
+
return super unless @attributes.has_key?(attr.reader)
|
|
24
|
+
if attr.writer?
|
|
25
|
+
# "args.size > 1" allows to simulate 1.8 behavior of "*args"
|
|
26
|
+
@attributes[attr.reader] = (args.size > 1) ? args : args.first
|
|
27
|
+
else
|
|
28
|
+
@attributes[attr.reader]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Process the provided attributes casting them to their proper values if a
|
|
33
|
+
# field exists for them on the +Document+. This will be limited to only the
|
|
34
|
+
# attributes provided in the suppied +Hash+ so that no extra nil values get
|
|
35
|
+
# put into the document's attributes.
|
|
36
|
+
def process(attrs = nil)
|
|
37
|
+
(attrs || {}).each_pair do |key, value|
|
|
38
|
+
if set_allowed?(key)
|
|
39
|
+
@attributes[key.to_s] = value
|
|
40
|
+
elsif write_allowed?(key)
|
|
41
|
+
send("#{key}=", value)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
setup_modifications
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Read a value from the +Document+ attributes. If the value does not exist
|
|
48
|
+
# it will return nil.
|
|
49
|
+
#
|
|
50
|
+
# Options:
|
|
51
|
+
#
|
|
52
|
+
# name: The name of the attribute to get.
|
|
53
|
+
#
|
|
54
|
+
# Example:
|
|
55
|
+
#
|
|
56
|
+
# <tt>person.read_attribute(:title)</tt>
|
|
57
|
+
def read_attribute(name)
|
|
58
|
+
access = name.to_s
|
|
59
|
+
fields[access].get(@attributes[access])
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Remove a value from the +Document+ attributes. If the value does not exist
|
|
63
|
+
# it will fail gracefully.
|
|
64
|
+
#
|
|
65
|
+
# Options:
|
|
66
|
+
#
|
|
67
|
+
# name: The name of the attribute to remove.
|
|
68
|
+
#
|
|
69
|
+
# Example:
|
|
70
|
+
#
|
|
71
|
+
# <tt>person.remove_attribute(:title)</tt>
|
|
72
|
+
def remove_attribute(name)
|
|
73
|
+
@attributes.delete(name.to_s)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the object type. This corresponds to the name of the class that
|
|
77
|
+
# this +Document+ is, which is used in determining the class to
|
|
78
|
+
# instantiate in various cases.
|
|
79
|
+
def _type
|
|
80
|
+
@attributes["_type"]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Set the type of the +Document+. This should be the name of the class.
|
|
84
|
+
def _type=(new_type)
|
|
85
|
+
@attributes["_type"] = new_type
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Write a single attribute to the +Document+ attribute +Hash+. This will
|
|
89
|
+
# also fire the before and after update callbacks, and perform any
|
|
90
|
+
# necessary typecasting.
|
|
91
|
+
#
|
|
92
|
+
# Options:
|
|
93
|
+
#
|
|
94
|
+
# name: The name of the attribute to update.
|
|
95
|
+
# value: The value to set for the attribute.
|
|
96
|
+
#
|
|
97
|
+
# Example:
|
|
98
|
+
#
|
|
99
|
+
# <tt>person.write_attribute(:title, "Mr.")</tt>
|
|
100
|
+
#
|
|
101
|
+
# This will also cause the observing +Document+ to notify it's parent if
|
|
102
|
+
# there is any.
|
|
103
|
+
def write_attribute(name, value)
|
|
104
|
+
access = name.to_s
|
|
105
|
+
modify(access, @attributes[access], fields[access].set(value))
|
|
106
|
+
notify unless id.blank?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Writes the supplied attributes +Hash+ to the +Document+. This will only
|
|
110
|
+
# overwrite existing attributes if they are present in the new +Hash+, all
|
|
111
|
+
# others will be preserved.
|
|
112
|
+
#
|
|
113
|
+
# Options:
|
|
114
|
+
#
|
|
115
|
+
# attrs: The +Hash+ of new attributes to set on the +Document+
|
|
116
|
+
#
|
|
117
|
+
# Example:
|
|
118
|
+
#
|
|
119
|
+
# <tt>person.write_attributes(:title => "Mr.")</tt>
|
|
120
|
+
#
|
|
121
|
+
# This will also cause the observing +Document+ to notify it's parent if
|
|
122
|
+
# there is any.
|
|
123
|
+
def write_attributes(attrs = nil)
|
|
124
|
+
process(attrs || {})
|
|
125
|
+
identify if id.blank?
|
|
126
|
+
notify
|
|
127
|
+
end
|
|
128
|
+
alias :attributes= :write_attributes
|
|
129
|
+
|
|
130
|
+
protected
|
|
131
|
+
# Return true if dynamic field setting is enabled.
|
|
132
|
+
def set_allowed?(key)
|
|
133
|
+
Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Used when supplying a :reject_if block as an option to
|
|
137
|
+
# accepts_nested_attributes_for
|
|
138
|
+
def reject(attributes, options)
|
|
139
|
+
rejector = options[:reject_if]
|
|
140
|
+
if rejector
|
|
141
|
+
attributes.delete_if do |key, value|
|
|
142
|
+
rejector.call(value)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Return true if writing to the given field is allowed
|
|
148
|
+
def write_allowed?(key)
|
|
149
|
+
return true unless fields[key.to_s]
|
|
150
|
+
fields[key.to_s].accessible?
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
module ClassMethods
|
|
155
|
+
# Defines attribute setters for the associations specified by the names.
|
|
156
|
+
# This will work for a has one or has many association.
|
|
157
|
+
#
|
|
158
|
+
# Example:
|
|
159
|
+
#
|
|
160
|
+
# class Person
|
|
161
|
+
# include Mongoid::Document
|
|
162
|
+
# embeds_one :name
|
|
163
|
+
# embeds_many :addresses
|
|
164
|
+
#
|
|
165
|
+
# accepts_nested_attributes_for :name, :addresses
|
|
166
|
+
# end
|
|
167
|
+
def accepts_nested_attributes_for(*args)
|
|
168
|
+
associations = args.flatten
|
|
169
|
+
options = associations.last.is_a?(Hash) ? associations.pop : {}
|
|
170
|
+
associations.each do |name|
|
|
171
|
+
define_method("#{name}_attributes=") do |attrs|
|
|
172
|
+
reject(attrs, options)
|
|
173
|
+
association = send(name)
|
|
174
|
+
if association
|
|
175
|
+
observe(association, true)
|
|
176
|
+
association.nested_build(attrs)
|
|
177
|
+
else
|
|
178
|
+
send("build_#{name}", attrs)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Callbacks
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
included do
|
|
6
|
+
extend ActiveModel::Callbacks
|
|
7
|
+
|
|
8
|
+
# Define all the callbacks that are accepted by the document.
|
|
9
|
+
define_model_callbacks \
|
|
10
|
+
:create,
|
|
11
|
+
:destroy,
|
|
12
|
+
:save,
|
|
13
|
+
:update,
|
|
14
|
+
:validate,
|
|
15
|
+
:terminator => false
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "mongoid/collections/operations"
|
|
3
|
+
require "mongoid/collections/cyclic_iterator"
|
|
4
|
+
require "mongoid/collections/mimic"
|
|
5
|
+
require "mongoid/collections/master"
|
|
6
|
+
require "mongoid/collections/slaves"
|
|
7
|
+
|
|
8
|
+
module Mongoid #:nodoc
|
|
9
|
+
class Collection
|
|
10
|
+
include Collections::Mimic
|
|
11
|
+
attr_reader :counter, :name
|
|
12
|
+
|
|
13
|
+
# All write operations should delegate to the master connection. These
|
|
14
|
+
# operations mimic the methods on a Mongo:Collection.
|
|
15
|
+
#
|
|
16
|
+
# Example:
|
|
17
|
+
#
|
|
18
|
+
# <tt>collection.save({ :name => "Al" })</tt>
|
|
19
|
+
proxy(:master, Collections::Operations::PROXIED)
|
|
20
|
+
|
|
21
|
+
# Determines where to send the next read query. If the slaves are not
|
|
22
|
+
# defined then send to master. If the read counter is under the configured
|
|
23
|
+
# maximum then return the master. In any other case return the slaves.
|
|
24
|
+
#
|
|
25
|
+
# Example:
|
|
26
|
+
#
|
|
27
|
+
# <tt>collection.directed</tt>
|
|
28
|
+
#
|
|
29
|
+
# Return:
|
|
30
|
+
#
|
|
31
|
+
# Either a +Master+ or +Slaves+ collection.
|
|
32
|
+
def directed(options = {})
|
|
33
|
+
options.delete(:cache)
|
|
34
|
+
enslave = options.delete(:enslave) || @klass.enslaved?
|
|
35
|
+
enslave ? master_or_slaves : master
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Find documents from the database given a selector and options.
|
|
39
|
+
#
|
|
40
|
+
# Options:
|
|
41
|
+
#
|
|
42
|
+
# selector: A +Hash+ selector that is the query.
|
|
43
|
+
# options: The options to pass to the db.
|
|
44
|
+
#
|
|
45
|
+
# Example:
|
|
46
|
+
#
|
|
47
|
+
# <tt>collection.find({ :test => "value" })</tt>
|
|
48
|
+
def find(selector = {}, options = {})
|
|
49
|
+
cursor = Mongoid::Cursor.new(@klass, self, directed(options).find(selector, options))
|
|
50
|
+
if block_given?
|
|
51
|
+
yield cursor; cursor.close
|
|
52
|
+
else
|
|
53
|
+
cursor
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Find the first document from the database given a selector and options.
|
|
58
|
+
#
|
|
59
|
+
# Options:
|
|
60
|
+
#
|
|
61
|
+
# selector: A +Hash+ selector that is the query.
|
|
62
|
+
# options: The options to pass to the db.
|
|
63
|
+
#
|
|
64
|
+
# Example:
|
|
65
|
+
#
|
|
66
|
+
# <tt>collection.find_one({ :test => "value" })</tt>
|
|
67
|
+
def find_one(selector = {}, options = {})
|
|
68
|
+
directed(options).find_one(selector, options)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Initialize a new Mongoid::Collection, setting up the master, slave, and
|
|
72
|
+
# name attributes. Masters will be used for writes, slaves for reads.
|
|
73
|
+
#
|
|
74
|
+
# Example:
|
|
75
|
+
#
|
|
76
|
+
# <tt>Mongoid::Collection.new(masters, slaves, "test")</tt>
|
|
77
|
+
def initialize(klass, name)
|
|
78
|
+
@klass, @name = klass, name
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Perform a map/reduce on the documents.
|
|
82
|
+
#
|
|
83
|
+
# Options:
|
|
84
|
+
#
|
|
85
|
+
# map: The map javascript funcdtion.
|
|
86
|
+
# reduce: The reduce javascript function.
|
|
87
|
+
def map_reduce(map, reduce, options = {})
|
|
88
|
+
directed(options).map_reduce(map, reduce, options)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
alias :mapreduce :map_reduce
|
|
92
|
+
|
|
93
|
+
# Return the object responsible for writes to the database. This will
|
|
94
|
+
# always return a collection associated with the Master DB.
|
|
95
|
+
#
|
|
96
|
+
# Example:
|
|
97
|
+
#
|
|
98
|
+
# <tt>collection.writer</tt>
|
|
99
|
+
def master
|
|
100
|
+
@master ||= Collections::Master.new(Mongoid.master, @name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Return the object responsible for reading documents from the database.
|
|
104
|
+
# This is usually the slave databases, but in their absence the master will
|
|
105
|
+
# handle the task.
|
|
106
|
+
#
|
|
107
|
+
# Example:
|
|
108
|
+
#
|
|
109
|
+
# <tt>collection.reader</tt>
|
|
110
|
+
def slaves
|
|
111
|
+
@slaves ||= Collections::Slaves.new(Mongoid.slaves, @name)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
protected
|
|
115
|
+
def master_or_slaves
|
|
116
|
+
slaves.empty? ? master : slaves
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|