mongoid-braxton 2.0.2
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/LICENSE +20 -0
- data/README.rdoc +50 -0
- data/Rakefile +51 -0
- data/lib/config/locales/bg.yml +41 -0
- data/lib/config/locales/de.yml +41 -0
- data/lib/config/locales/en.yml +45 -0
- data/lib/config/locales/es.yml +41 -0
- data/lib/config/locales/fr.yml +42 -0
- data/lib/config/locales/hu.yml +44 -0
- data/lib/config/locales/id.yml +46 -0
- data/lib/config/locales/it.yml +39 -0
- data/lib/config/locales/ja.yml +40 -0
- data/lib/config/locales/kr.yml +65 -0
- data/lib/config/locales/nl.yml +39 -0
- data/lib/config/locales/pl.yml +39 -0
- data/lib/config/locales/pt-BR.yml +40 -0
- data/lib/config/locales/pt.yml +40 -0
- data/lib/config/locales/ro.yml +46 -0
- data/lib/config/locales/ru.yml +41 -0
- data/lib/config/locales/sv.yml +40 -0
- data/lib/config/locales/vi.yml +45 -0
- data/lib/config/locales/zh-CN.yml +33 -0
- data/lib/mongoid.rb +140 -0
- data/lib/mongoid/atomicity.rb +111 -0
- data/lib/mongoid/attributes.rb +185 -0
- data/lib/mongoid/attributes/processing.rb +145 -0
- data/lib/mongoid/callbacks.rb +23 -0
- data/lib/mongoid/collection.rb +137 -0
- data/lib/mongoid/collections.rb +71 -0
- data/lib/mongoid/collections/master.rb +37 -0
- data/lib/mongoid/collections/operations.rb +42 -0
- data/lib/mongoid/collections/retry.rb +39 -0
- data/lib/mongoid/components.rb +45 -0
- data/lib/mongoid/config.rb +349 -0
- data/lib/mongoid/config/database.rb +167 -0
- data/lib/mongoid/config/replset_database.rb +78 -0
- data/lib/mongoid/contexts.rb +19 -0
- data/lib/mongoid/contexts/enumerable.rb +275 -0
- data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
- data/lib/mongoid/contexts/mongo.rb +345 -0
- data/lib/mongoid/copyable.rb +46 -0
- data/lib/mongoid/criteria.rb +357 -0
- data/lib/mongoid/criterion/builder.rb +34 -0
- data/lib/mongoid/criterion/complex.rb +34 -0
- data/lib/mongoid/criterion/creational.rb +34 -0
- data/lib/mongoid/criterion/exclusion.rb +108 -0
- data/lib/mongoid/criterion/inclusion.rb +198 -0
- data/lib/mongoid/criterion/inspection.rb +22 -0
- data/lib/mongoid/criterion/optional.rb +193 -0
- data/lib/mongoid/criterion/selector.rb +143 -0
- data/lib/mongoid/criterion/unconvertable.rb +20 -0
- data/lib/mongoid/cursor.rb +86 -0
- data/lib/mongoid/default_scope.rb +36 -0
- data/lib/mongoid/dirty.rb +253 -0
- data/lib/mongoid/document.rb +284 -0
- data/lib/mongoid/errors.rb +13 -0
- data/lib/mongoid/errors/document_not_found.rb +29 -0
- data/lib/mongoid/errors/invalid_collection.rb +19 -0
- data/lib/mongoid/errors/invalid_database.rb +20 -0
- data/lib/mongoid/errors/invalid_field.rb +19 -0
- data/lib/mongoid/errors/invalid_options.rb +16 -0
- data/lib/mongoid/errors/invalid_type.rb +26 -0
- data/lib/mongoid/errors/mixed_relations.rb +37 -0
- data/lib/mongoid/errors/mongoid_error.rb +27 -0
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
- data/lib/mongoid/errors/unsaved_document.rb +23 -0
- data/lib/mongoid/errors/unsupported_version.rb +21 -0
- data/lib/mongoid/errors/validations.rb +24 -0
- data/lib/mongoid/extensions.rb +123 -0
- data/lib/mongoid/extensions/array/conversions.rb +23 -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 +27 -0
- data/lib/mongoid/extensions/date/conversions.rb +25 -0
- data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
- data/lib/mongoid/extensions/false_class/equality.rb +13 -0
- data/lib/mongoid/extensions/float/conversions.rb +20 -0
- data/lib/mongoid/extensions/hash/conversions.rb +19 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
- data/lib/mongoid/extensions/hash/scoping.rb +12 -0
- data/lib/mongoid/extensions/integer/conversions.rb +20 -0
- data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
- data/lib/mongoid/extensions/object/checks.rb +32 -0
- data/lib/mongoid/extensions/object/conversions.rb +25 -0
- data/lib/mongoid/extensions/object/reflections.rb +17 -0
- data/lib/mongoid/extensions/object/yoda.rb +27 -0
- data/lib/mongoid/extensions/object_id/conversions.rb +96 -0
- data/lib/mongoid/extensions/proc/scoping.rb +12 -0
- data/lib/mongoid/extensions/range/conversions.rb +25 -0
- data/lib/mongoid/extensions/set/conversions.rb +20 -0
- data/lib/mongoid/extensions/string/conversions.rb +34 -0
- data/lib/mongoid/extensions/string/inflections.rb +97 -0
- data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
- data/lib/mongoid/extensions/time_conversions.rb +38 -0
- data/lib/mongoid/extensions/true_class/equality.rb +13 -0
- data/lib/mongoid/extras.rb +42 -0
- data/lib/mongoid/factory.rb +37 -0
- data/lib/mongoid/field.rb +162 -0
- data/lib/mongoid/fields.rb +183 -0
- data/lib/mongoid/finders.rb +127 -0
- data/lib/mongoid/hierarchy.rb +85 -0
- data/lib/mongoid/identity.rb +92 -0
- data/lib/mongoid/indexes.rb +38 -0
- data/lib/mongoid/inspection.rb +54 -0
- data/lib/mongoid/javascript.rb +21 -0
- data/lib/mongoid/javascript/functions.yml +37 -0
- data/lib/mongoid/json.rb +16 -0
- data/lib/mongoid/keys.rb +131 -0
- data/lib/mongoid/logger.rb +18 -0
- data/lib/mongoid/matchers.rb +32 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +70 -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/or.rb +30 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/lib/mongoid/matchers/strategies.rb +63 -0
- data/lib/mongoid/multi_database.rb +11 -0
- data/lib/mongoid/multi_parameter_attributes.rb +82 -0
- data/lib/mongoid/named_scope.rb +137 -0
- data/lib/mongoid/nested_attributes.rb +51 -0
- data/lib/mongoid/observer.rb +67 -0
- data/lib/mongoid/paranoia.rb +103 -0
- data/lib/mongoid/paths.rb +61 -0
- data/lib/mongoid/persistence.rb +240 -0
- data/lib/mongoid/persistence/atomic.rb +88 -0
- data/lib/mongoid/persistence/atomic/add_to_set.rb +32 -0
- data/lib/mongoid/persistence/atomic/inc.rb +28 -0
- data/lib/mongoid/persistence/atomic/operation.rb +44 -0
- data/lib/mongoid/persistence/atomic/pull_all.rb +33 -0
- data/lib/mongoid/persistence/atomic/push.rb +28 -0
- data/lib/mongoid/persistence/command.rb +71 -0
- data/lib/mongoid/persistence/insert.rb +53 -0
- data/lib/mongoid/persistence/insert_embedded.rb +43 -0
- data/lib/mongoid/persistence/remove.rb +44 -0
- data/lib/mongoid/persistence/remove_all.rb +40 -0
- data/lib/mongoid/persistence/remove_embedded.rb +48 -0
- data/lib/mongoid/persistence/update.rb +77 -0
- data/lib/mongoid/railtie.rb +139 -0
- data/lib/mongoid/railties/database.rake +171 -0
- data/lib/mongoid/railties/document.rb +12 -0
- data/lib/mongoid/relations.rb +107 -0
- data/lib/mongoid/relations/accessors.rb +175 -0
- data/lib/mongoid/relations/auto_save.rb +34 -0
- data/lib/mongoid/relations/binding.rb +26 -0
- data/lib/mongoid/relations/bindings.rb +9 -0
- data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
- data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
- data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
- data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
- data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +103 -0
- data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
- data/lib/mongoid/relations/builder.rb +42 -0
- data/lib/mongoid/relations/builders.rb +79 -0
- data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
- data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
- data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +126 -0
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
- data/lib/mongoid/relations/builders/referenced/in.rb +29 -0
- data/lib/mongoid/relations/builders/referenced/many.rb +47 -0
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
- data/lib/mongoid/relations/builders/referenced/one.rb +27 -0
- data/lib/mongoid/relations/cascading.rb +55 -0
- data/lib/mongoid/relations/cascading/delete.rb +19 -0
- data/lib/mongoid/relations/cascading/destroy.rb +19 -0
- data/lib/mongoid/relations/cascading/nullify.rb +18 -0
- data/lib/mongoid/relations/cascading/strategy.rb +26 -0
- data/lib/mongoid/relations/constraint.rb +42 -0
- data/lib/mongoid/relations/cyclic.rb +103 -0
- data/lib/mongoid/relations/embedded/atomic.rb +86 -0
- data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
- data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
- data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
- data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
- data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
- data/lib/mongoid/relations/embedded/in.rb +173 -0
- data/lib/mongoid/relations/embedded/many.rb +499 -0
- data/lib/mongoid/relations/embedded/one.rb +170 -0
- data/lib/mongoid/relations/macros.rb +310 -0
- data/lib/mongoid/relations/many.rb +215 -0
- data/lib/mongoid/relations/metadata.rb +539 -0
- data/lib/mongoid/relations/nested_builder.rb +68 -0
- data/lib/mongoid/relations/one.rb +47 -0
- data/lib/mongoid/relations/polymorphic.rb +54 -0
- data/lib/mongoid/relations/proxy.rb +143 -0
- data/lib/mongoid/relations/referenced/batch.rb +71 -0
- data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
- data/lib/mongoid/relations/referenced/in.rb +216 -0
- data/lib/mongoid/relations/referenced/many.rb +516 -0
- data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
- data/lib/mongoid/relations/referenced/one.rb +222 -0
- data/lib/mongoid/relations/reflections.rb +45 -0
- data/lib/mongoid/safe.rb +23 -0
- data/lib/mongoid/safety.rb +207 -0
- data/lib/mongoid/scope.rb +31 -0
- data/lib/mongoid/serialization.rb +99 -0
- data/lib/mongoid/sharding.rb +51 -0
- data/lib/mongoid/state.rb +67 -0
- data/lib/mongoid/timestamps.rb +14 -0
- data/lib/mongoid/timestamps/created.rb +31 -0
- data/lib/mongoid/timestamps/updated.rb +33 -0
- data/lib/mongoid/validations.rb +124 -0
- data/lib/mongoid/validations/associated.rb +44 -0
- data/lib/mongoid/validations/referenced.rb +58 -0
- data/lib/mongoid/validations/uniqueness.rb +85 -0
- data/lib/mongoid/version.rb +4 -0
- data/lib/mongoid/versioning.rb +113 -0
- data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb +19 -0
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
- data/lib/rails/generators/mongoid/observer/templates/observer.rb +4 -0
- data/lib/rails/generators/mongoid_generator.rb +70 -0
- data/lib/rails/mongoid.rb +58 -0
- metadata +406 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# @todo: Durran: This module needs an overhaul.
|
|
5
|
+
module MultiParameterAttributes
|
|
6
|
+
module Errors
|
|
7
|
+
# Raised when an error occurred while doing a mass assignment to an attribute through the
|
|
8
|
+
# <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
|
|
9
|
+
# offending attribute.
|
|
10
|
+
class AttributeAssignmentError < Mongoid::Errors::MongoidError
|
|
11
|
+
attr_reader :exception, :attribute
|
|
12
|
+
def initialize(message, exception, attribute)
|
|
13
|
+
@exception = exception
|
|
14
|
+
@attribute = attribute
|
|
15
|
+
@message = message
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Raised when there are multiple errors while doing a mass assignment through the +attributes+
|
|
20
|
+
# method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
|
|
21
|
+
# objects, each corresponding to the error while assigning to an attribute.
|
|
22
|
+
class MultiparameterAssignmentErrors < Mongoid::Errors::MongoidError
|
|
23
|
+
attr_reader :errors
|
|
24
|
+
def initialize(errors)
|
|
25
|
+
@errors = errors
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def process(attrs = nil, guard_protected_attributes = true)
|
|
31
|
+
if attrs
|
|
32
|
+
errors = []
|
|
33
|
+
attributes = {}
|
|
34
|
+
multi_parameter_attributes = {}
|
|
35
|
+
|
|
36
|
+
attrs.each_pair do |key, value|
|
|
37
|
+
if key =~ /^([^\(]+)\((\d+)([if])\)$/
|
|
38
|
+
key, index = $1, $2.to_i
|
|
39
|
+
(multi_parameter_attributes[key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
|
|
40
|
+
else
|
|
41
|
+
attributes[key] = value
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
multi_parameter_attributes.each_pair do |key, values|
|
|
46
|
+
begin
|
|
47
|
+
values = (values.keys.min..values.keys.max).map { |i| values[i] }
|
|
48
|
+
klass = self.class.fields[key].try(:type)
|
|
49
|
+
attributes[key] = instantiate_object(klass, values)
|
|
50
|
+
rescue => e
|
|
51
|
+
errors << Errors::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{key}", e, key)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
unless errors.empty?
|
|
56
|
+
raise Errors::MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
super attributes, guard_protected_attributes
|
|
60
|
+
else
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
|
|
67
|
+
def instantiate_object(klass, values_with_empty_parameters)
|
|
68
|
+
return nil if values_with_empty_parameters.all? { |v| v.nil? }
|
|
69
|
+
|
|
70
|
+
values = values_with_empty_parameters.collect { |v| v.nil? ? 1 : v }
|
|
71
|
+
|
|
72
|
+
if klass == DateTime || klass == Date || klass == Time
|
|
73
|
+
klass.send(:convert_to_time, values)
|
|
74
|
+
elsif klass
|
|
75
|
+
klass.new *values
|
|
76
|
+
else
|
|
77
|
+
values
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# This module contains the named scoping behaviour.
|
|
5
|
+
module NamedScope
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
class_attribute :scopes
|
|
10
|
+
self.scopes = {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods #:nodoc:
|
|
14
|
+
|
|
15
|
+
# Gets either the last scope on the stack or creates a new criteria.
|
|
16
|
+
#
|
|
17
|
+
# @example Get the last or new.
|
|
18
|
+
# Person.scoping(true)
|
|
19
|
+
#
|
|
20
|
+
# @param [ true, false ] embedded Is this scope for an embedded doc?
|
|
21
|
+
# @param [ true, false ] scoped Are we applying default scoping?
|
|
22
|
+
#
|
|
23
|
+
# @return [ Criteria ] The last scope or a new one.
|
|
24
|
+
#
|
|
25
|
+
# @since 2.0.0
|
|
26
|
+
def criteria(embedded = false, scoped = true)
|
|
27
|
+
scope_stack.last || Criteria.new(self, embedded).tap do |crit|
|
|
28
|
+
return crit.fuse(default_scoping) if default_scoping && scoped
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Creates a named_scope for the +Document+, similar to ActiveRecord's
|
|
33
|
+
# named_scopes. +NamedScopes+ are proxied +Criteria+ objects that can be
|
|
34
|
+
# chained.
|
|
35
|
+
#
|
|
36
|
+
# @example Create named scopes.
|
|
37
|
+
#
|
|
38
|
+
# class Person
|
|
39
|
+
# include Mongoid::Document
|
|
40
|
+
# field :active, :type => Boolean
|
|
41
|
+
# field :count, :type => Integer
|
|
42
|
+
#
|
|
43
|
+
# scope :active, :where => { :active => true }
|
|
44
|
+
# scope :count_gt_one, :where => { :count.gt => 1 }
|
|
45
|
+
# scope :at_least_count, lambda { |count| { :where => { :count.gt => count } } }
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# @param [ Symbol ] name The name of the scope.
|
|
49
|
+
# @param [ Hash, Criteria ] conditions The conditions of the scope.
|
|
50
|
+
#
|
|
51
|
+
# @since 1.0.0
|
|
52
|
+
def scope(name, conditions = {}, &block)
|
|
53
|
+
name = name.to_sym
|
|
54
|
+
valid_scope_name?(name)
|
|
55
|
+
scopes[name] = Scope.new(conditions, &block)
|
|
56
|
+
(class << self; self; end).class_eval <<-EOT
|
|
57
|
+
def #{name}(*args)
|
|
58
|
+
scope = scopes[:#{name}]
|
|
59
|
+
scope.extend(criteria.fuse(scope.conditions.scoped(*args)))
|
|
60
|
+
end
|
|
61
|
+
EOT
|
|
62
|
+
end
|
|
63
|
+
alias :named_scope :scope
|
|
64
|
+
|
|
65
|
+
# Get a criteria object for the class, scoped to the default if defined.
|
|
66
|
+
#
|
|
67
|
+
# @example Get a scoped criteria.
|
|
68
|
+
# Person.scoped
|
|
69
|
+
#
|
|
70
|
+
# @param [ true, false ] embedded Is the criteria for embedded docs?
|
|
71
|
+
#
|
|
72
|
+
# @return [ Criteria ] The scoped criteria.
|
|
73
|
+
#
|
|
74
|
+
# @since 2.0.0
|
|
75
|
+
def scoped(embedded = false)
|
|
76
|
+
criteria(embedded, true)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Initializes and returns the current scope stack.
|
|
80
|
+
#
|
|
81
|
+
# @example Get the scope stack.
|
|
82
|
+
# Person.scope_stack
|
|
83
|
+
#
|
|
84
|
+
# @return [ Array<Criteria> ] The scope stack.
|
|
85
|
+
#
|
|
86
|
+
# @since 1.0.0
|
|
87
|
+
def scope_stack
|
|
88
|
+
scope_stack_for = Thread.current[:mongoid_scope_stack] ||= {}
|
|
89
|
+
scope_stack_for[object_id] ||= []
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Get a criteria object for the class, ignoring default scoping.
|
|
93
|
+
#
|
|
94
|
+
# @example Get an unscoped criteria.
|
|
95
|
+
# Person.scoped
|
|
96
|
+
#
|
|
97
|
+
# @param [ true, false ] embedded Is the criteria for embedded docs?
|
|
98
|
+
#
|
|
99
|
+
# @return [ Criteria ] The unscoped criteria.
|
|
100
|
+
#
|
|
101
|
+
# @since 2.0.0
|
|
102
|
+
def unscoped(embedded = false)
|
|
103
|
+
criteria(embedded, false)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Pushes the provided criteria onto the scope stack, and removes it after the
|
|
107
|
+
# provided block is yielded.
|
|
108
|
+
#
|
|
109
|
+
# @example Yield to the criteria.
|
|
110
|
+
# Person.with_scope(criteria)
|
|
111
|
+
#
|
|
112
|
+
# @param [ Criteria ] criteria The criteria to apply.
|
|
113
|
+
#
|
|
114
|
+
# @return [ Criteria ] The yielded criteria.
|
|
115
|
+
#
|
|
116
|
+
# @since 1.0.0
|
|
117
|
+
def with_scope(criteria)
|
|
118
|
+
scope_stack = self.scope_stack
|
|
119
|
+
scope_stack << criteria
|
|
120
|
+
begin
|
|
121
|
+
yield criteria
|
|
122
|
+
ensure
|
|
123
|
+
scope_stack.pop
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
protected
|
|
128
|
+
|
|
129
|
+
def valid_scope_name?(name)
|
|
130
|
+
if !scopes[name] && respond_to?(name, true)
|
|
131
|
+
Mongoid.logger.warn "Creating scope :#{name}. " \
|
|
132
|
+
"Overwriting existing method #{self.name}.#{name}." if Mongoid.logger
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module NestedAttributes
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
class_attribute :nested_attributes
|
|
8
|
+
self.nested_attributes = []
|
|
9
|
+
|
|
10
|
+
delegate :nested_attributes, :to => "self.class"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods
|
|
14
|
+
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |_, value| value.blank? } }
|
|
15
|
+
|
|
16
|
+
# Used when needing to update related models from a parent relation. Can
|
|
17
|
+
# be used on embedded or referenced relations.
|
|
18
|
+
#
|
|
19
|
+
# @example Defining nested attributes.
|
|
20
|
+
#
|
|
21
|
+
# class Person
|
|
22
|
+
# include Mongoid::Document
|
|
23
|
+
#
|
|
24
|
+
# embeds_many :addresses
|
|
25
|
+
# embeds_one :game
|
|
26
|
+
# references_many :posts
|
|
27
|
+
#
|
|
28
|
+
# accepts_nested_attributes_for :addresses, :game, :posts
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# @param [ Array<Symbol>, Hash ] *args A list of relation names, followed
|
|
32
|
+
# by a hash of options.
|
|
33
|
+
#
|
|
34
|
+
# @option *args [ true, false ] :allow_destroy Can deletion occur?
|
|
35
|
+
# @option *args [ Proc ] :reject_if Block to reject documents with.
|
|
36
|
+
# @option *args [ Integer ] :limit The max number to create.
|
|
37
|
+
# @option *args [ true, false ] :update_only Only update existing docs.
|
|
38
|
+
def accepts_nested_attributes_for(*args)
|
|
39
|
+
options = args.extract_options!
|
|
40
|
+
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
|
|
41
|
+
args.each do |name|
|
|
42
|
+
self.nested_attributes += [ "#{name}_attributes=" ]
|
|
43
|
+
define_method("#{name}_attributes=") do |attrs|
|
|
44
|
+
relation = relations[name.to_s]
|
|
45
|
+
relation.nested_builder(attrs, options).build(self)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# Mongoid observers hook into the lifecycle of documents.
|
|
5
|
+
class Observer < ActiveModel::Observer
|
|
6
|
+
|
|
7
|
+
# Instantiate the new observer. Will add all child observers as well.
|
|
8
|
+
#
|
|
9
|
+
# @example Instantiate the observer.
|
|
10
|
+
# Mongoid::Observer.new
|
|
11
|
+
#
|
|
12
|
+
# @since 2.0.0
|
|
13
|
+
def initialize
|
|
14
|
+
super and observed_descendants.each { |klass| add_observer!(klass) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
# Get all the child observers.
|
|
20
|
+
#
|
|
21
|
+
# @example Get the children.
|
|
22
|
+
# observer.observed_descendants
|
|
23
|
+
#
|
|
24
|
+
# @return [ Array<Class> ] The children.
|
|
25
|
+
#
|
|
26
|
+
# @since 2.0.0
|
|
27
|
+
def observed_descendants
|
|
28
|
+
observed_classes.sum([]) { |klass| klass.descendants }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Adds the specified observer to the class.
|
|
32
|
+
#
|
|
33
|
+
# @example Add the observer.
|
|
34
|
+
# observer.add_observer!(Document)
|
|
35
|
+
#
|
|
36
|
+
# @param [ Class ] klass The child observer to add.
|
|
37
|
+
#
|
|
38
|
+
# @since 2.0.0
|
|
39
|
+
def add_observer!(klass)
|
|
40
|
+
super and define_callbacks(klass)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Defines all the callbacks for each observer of the model.
|
|
44
|
+
#
|
|
45
|
+
# @example Define all the callbacks.
|
|
46
|
+
# observer.define_callbacks(Document)
|
|
47
|
+
#
|
|
48
|
+
# @param [ Class ] klass The model to define them on.
|
|
49
|
+
#
|
|
50
|
+
# @since 2.0.0
|
|
51
|
+
def define_callbacks(klass)
|
|
52
|
+
tap do |observer|
|
|
53
|
+
observer_name = observer.class.name.underscore.gsub('/', '__')
|
|
54
|
+
Mongoid::Callbacks::CALLBACKS.each do |callback|
|
|
55
|
+
next unless respond_to?(callback)
|
|
56
|
+
callback_meth = :"_notify_#{observer_name}_for_#{callback}"
|
|
57
|
+
unless klass.respond_to?(callback_meth)
|
|
58
|
+
klass.send(:define_method, callback_meth) do |&block|
|
|
59
|
+
observer.send(callback, self, &block)
|
|
60
|
+
end
|
|
61
|
+
klass.send(callback, callback_meth)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
# Include this module to get soft deletion of root level documents.
|
|
4
|
+
# This will add a deleted_at field to the +Document+, managed automatically.
|
|
5
|
+
# Potentially incompatible with unique indices. (if collisions with deleted items)
|
|
6
|
+
#
|
|
7
|
+
# To use:
|
|
8
|
+
#
|
|
9
|
+
# class Person
|
|
10
|
+
# include Mongoid::Document
|
|
11
|
+
# include Mongoid::Paranoia
|
|
12
|
+
# end
|
|
13
|
+
module Paranoia
|
|
14
|
+
extend ActiveSupport::Concern
|
|
15
|
+
|
|
16
|
+
included do
|
|
17
|
+
field :deleted_at, :type => Time
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Delete the paranoid +Document+ from the database completely. This will
|
|
21
|
+
# run the destroy callbacks.
|
|
22
|
+
#
|
|
23
|
+
# Example:
|
|
24
|
+
#
|
|
25
|
+
# <tt>document.destroy!</tt>
|
|
26
|
+
def destroy!
|
|
27
|
+
run_callbacks(:destroy) { delete! }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Delete the paranoid +Document+ from the database completely.
|
|
31
|
+
#
|
|
32
|
+
# Example:
|
|
33
|
+
#
|
|
34
|
+
# <tt>document.delete!</tt>
|
|
35
|
+
def delete!
|
|
36
|
+
@destroyed = true
|
|
37
|
+
Mongoid::Persistence::Remove.new(self).persist
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Delete the +Document+, will set the deleted_at timestamp and not actually
|
|
41
|
+
# delete it.
|
|
42
|
+
#
|
|
43
|
+
# Example:
|
|
44
|
+
#
|
|
45
|
+
# <tt>document.remove</tt>
|
|
46
|
+
#
|
|
47
|
+
# Returns:
|
|
48
|
+
#
|
|
49
|
+
# true
|
|
50
|
+
def remove(options = {})
|
|
51
|
+
now = Time.now
|
|
52
|
+
collection.update({ :_id => id }, { '$set' => { :deleted_at => now } })
|
|
53
|
+
@attributes["deleted_at"] = now
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
alias :delete :remove
|
|
58
|
+
|
|
59
|
+
# Determines if this document is destroyed.
|
|
60
|
+
#
|
|
61
|
+
# Returns:
|
|
62
|
+
#
|
|
63
|
+
# true if the +Document+ was destroyed.
|
|
64
|
+
def destroyed?
|
|
65
|
+
@destroyed || !!deleted_at
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Restores a previously soft-deleted document. Handles this by removing the
|
|
69
|
+
# deleted_at flag.
|
|
70
|
+
#
|
|
71
|
+
# Example:
|
|
72
|
+
#
|
|
73
|
+
# <tt>document.restore</tt>
|
|
74
|
+
def restore
|
|
75
|
+
collection.update({ :_id => id }, { '$unset' => { :deleted_at => true } })
|
|
76
|
+
@attributes.delete("deleted_at")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
module ClassMethods #:nodoc:
|
|
80
|
+
|
|
81
|
+
# Override the default +Criteria+ accessor to only get existing
|
|
82
|
+
# documents. Passes all arguments up to +NamedScope.criteria+
|
|
83
|
+
#
|
|
84
|
+
# Returns:
|
|
85
|
+
#
|
|
86
|
+
# A +Criteria+ for deleted_at not existing.
|
|
87
|
+
def criteria(*args)
|
|
88
|
+
super.where(:deleted_at.exists => false)
|
|
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>
|
|
98
|
+
def deleted
|
|
99
|
+
where(:deleted_at.exists => true)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|