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,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
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Extensions #:nodoc:
|
|
4
|
+
module Symbol #:nodoc:
|
|
5
|
+
module Inflections #:nodoc:
|
|
6
|
+
|
|
7
|
+
REVERSALS = {
|
|
8
|
+
:asc => :desc,
|
|
9
|
+
:ascending => :descending,
|
|
10
|
+
:desc => :asc,
|
|
11
|
+
:descending => :ascending
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def invert
|
|
15
|
+
REVERSALS[self]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def singular?
|
|
19
|
+
to_s.singular?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def plural?
|
|
23
|
+
to_s.plural?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
[ "asc", "ascending", "desc", "descending", "gt", "lt", "gte",
|
|
27
|
+
"lte", "ne", "near", "in", "nin", "mod", "all", "size", "exists",
|
|
28
|
+
"within", ["matches","elemMatch"] ].each do |oper|
|
|
29
|
+
m, oper = oper
|
|
30
|
+
oper = m unless oper
|
|
31
|
+
class_eval <<-OPERATORS
|
|
32
|
+
def #{m}
|
|
33
|
+
Criterion::Complex.new(:key => self, :operator => "#{oper}")
|
|
34
|
+
end
|
|
35
|
+
OPERATORS
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Mongoid #:nodoc:
|
|
2
|
+
module Extensions #:nodoc:
|
|
3
|
+
module TimeConversions #:nodoc:
|
|
4
|
+
def set(value)
|
|
5
|
+
return nil if value.blank?
|
|
6
|
+
time = convert_to_time(value)
|
|
7
|
+
strip_milliseconds(time).utc
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(value)
|
|
11
|
+
return nil if value.blank?
|
|
12
|
+
value = value.getlocal unless Mongoid::Config.use_utc?
|
|
13
|
+
if Mongoid::Config.use_activesupport_time_zone?
|
|
14
|
+
time_zone = Mongoid::Config.use_utc? ? 'UTC' : Time.zone
|
|
15
|
+
value = value.in_time_zone(time_zone)
|
|
16
|
+
end
|
|
17
|
+
value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
def strip_milliseconds(time)
|
|
23
|
+
::Time.at(time.to_i)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def convert_to_time(value)
|
|
27
|
+
time = Mongoid::Config.use_activesupport_time_zone? ? ::Time.zone : ::Time
|
|
28
|
+
case value
|
|
29
|
+
when ::String then time.parse(value)
|
|
30
|
+
when ::DateTime then time.local(value.year, value.month, value.day, value.hour, value.min, value.sec)
|
|
31
|
+
when ::Date then time.local(value.year, value.month, value.day)
|
|
32
|
+
when ::Array then time.local(*value)
|
|
33
|
+
else value
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# Adds support for caching queries at the class level.
|
|
5
|
+
module Extras
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
class_attribute :cached
|
|
10
|
+
self.cached = false
|
|
11
|
+
delegate :cached?, :to => "self.class"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module ClassMethods #:nodoc
|
|
15
|
+
|
|
16
|
+
# Sets caching on for this class. This class level configuration will
|
|
17
|
+
# default all queries to cache the results of the first iteration over
|
|
18
|
+
# the cursor into an internal array. This should only be used for queries
|
|
19
|
+
# that return a small number of results or have small documents, as after
|
|
20
|
+
# the first iteration the entire results will be stored in memory.
|
|
21
|
+
#
|
|
22
|
+
# @example Cache all reads for the class.
|
|
23
|
+
# class Person
|
|
24
|
+
# include Mongoid::Document
|
|
25
|
+
# cache
|
|
26
|
+
# end
|
|
27
|
+
def cache
|
|
28
|
+
self.cached = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Determines if the class is cached or not.
|
|
32
|
+
#
|
|
33
|
+
# @example Are class reads cached?
|
|
34
|
+
# Document.cached?
|
|
35
|
+
#
|
|
36
|
+
# @return [ true, false ] If the reads are cached.
|
|
37
|
+
def cached?
|
|
38
|
+
!!self.cached
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# Instantiates documents that came from the database.
|
|
5
|
+
module Factory
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# Builds a new +Document+ from the supplied attributes.
|
|
9
|
+
#
|
|
10
|
+
# @example Build the document.
|
|
11
|
+
# Mongoid::Factory.build(Person, { "name" => "Durran" })
|
|
12
|
+
#
|
|
13
|
+
# @param [ Class ] klass The class to instantiate from if _type is not present.
|
|
14
|
+
# @param [ Hash ] attributes The document attributes.
|
|
15
|
+
#
|
|
16
|
+
# @return [ Document ] The instantiated document.
|
|
17
|
+
def build(klass, attributes = {})
|
|
18
|
+
type = (attributes || {})["_type"]
|
|
19
|
+
type.blank? ? klass.new(attributes) : type.constantize.new(attributes)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Builds a new +Document+ from the supplied attributes loaded from the
|
|
23
|
+
# database.
|
|
24
|
+
#
|
|
25
|
+
# @example Build the document.
|
|
26
|
+
# Mongoid::Factory.from_db(Person, { "name" => "Durran" })
|
|
27
|
+
#
|
|
28
|
+
# @param [ Class ] klass The class to instantiate from if _type is not present.
|
|
29
|
+
# @param [ Hash ] attributes The document attributes.
|
|
30
|
+
#
|
|
31
|
+
# @return [ Document ] The instantiated document.
|
|
32
|
+
def from_db(klass, attributes = {})
|
|
33
|
+
type = attributes["_type"]
|
|
34
|
+
type.blank? ? klass.instantiate(attributes) : type.constantize.instantiate(attributes)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
|
|
4
|
+
# Defines the behaviour for defined fields in the document.
|
|
5
|
+
class Field
|
|
6
|
+
|
|
7
|
+
NO_CAST_ON_READ = [
|
|
8
|
+
Array, Binary, Boolean, Float, Hash,
|
|
9
|
+
Integer, BSON::ObjectId, Set, String, Symbol
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
attr_accessor :type
|
|
13
|
+
attr_reader :copyable, :klass, :label, :name, :options
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
|
|
17
|
+
# Return a map of custom option names to their handlers.
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# Mongoid::Field.options
|
|
21
|
+
# # => { :required => #<Proc:0x00000100976b38> }
|
|
22
|
+
#
|
|
23
|
+
# @return [ Hash ] the option map
|
|
24
|
+
def options
|
|
25
|
+
@options ||= {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Stores the provided block to be run when the option name specified is
|
|
29
|
+
# defined on a field.
|
|
30
|
+
#
|
|
31
|
+
# No assumptions are made about what sort of work the handler might
|
|
32
|
+
# perform, so it will always be called if the `option_name` key is
|
|
33
|
+
# provided in the field definition -- even if it is false or nil.
|
|
34
|
+
#
|
|
35
|
+
# @example
|
|
36
|
+
# Mongoid::Field.option :required do |model, field, value|
|
|
37
|
+
# model.validates_presence_of field if value
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# @param [ Symbol ] option_name the option name to match against
|
|
41
|
+
# @param [ Proc ] block the handler to execute when the option is
|
|
42
|
+
# provided.
|
|
43
|
+
def option(option_name, &block)
|
|
44
|
+
options[option_name] = block
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# When reading the field do we need to cast the value? This holds true when
|
|
50
|
+
# times are stored or for big decimals which are stored as strings.
|
|
51
|
+
#
|
|
52
|
+
# @example Typecast on a read?
|
|
53
|
+
# field.cast_on_read?
|
|
54
|
+
#
|
|
55
|
+
# @return [ true, false ] If the field should be cast.
|
|
56
|
+
def cast_on_read?
|
|
57
|
+
!NO_CAST_ON_READ.include?(type)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Get the default value for the field.
|
|
61
|
+
#
|
|
62
|
+
# @example Get the default.
|
|
63
|
+
# field.default
|
|
64
|
+
#
|
|
65
|
+
# @return [ Object ] The typecast default value.
|
|
66
|
+
#
|
|
67
|
+
# @since 1.0.0
|
|
68
|
+
def default
|
|
69
|
+
copy.respond_to?(:call) ? copy : set(copy)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Create the new field with a name and optional additional options.
|
|
73
|
+
#
|
|
74
|
+
# @example Create the new field.
|
|
75
|
+
# Field.new(:name, :type => String)
|
|
76
|
+
#
|
|
77
|
+
# @param [ Hash ] options The field options.
|
|
78
|
+
#
|
|
79
|
+
# @option options [ Class ] :type The class of the field.
|
|
80
|
+
# @option options [ Object ] :default The default value for the field.
|
|
81
|
+
# @option options [ String ] :label The field's label.
|
|
82
|
+
#
|
|
83
|
+
# @since 1.0.0
|
|
84
|
+
def initialize(name, options = {})
|
|
85
|
+
@type = options[:type] || Object
|
|
86
|
+
@name, @default, @label = name, options[:default], options[:label]
|
|
87
|
+
@copyable = (@default.is_a?(Array) || @default.is_a?(Hash))
|
|
88
|
+
@options = options
|
|
89
|
+
check_default!
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Used for setting an object in the attributes hash.
|
|
93
|
+
#
|
|
94
|
+
# If nil is provided the default will get returned if it exists.
|
|
95
|
+
#
|
|
96
|
+
# If the field is an identity field, ie an id, it performs the necessary
|
|
97
|
+
# cast.
|
|
98
|
+
#
|
|
99
|
+
# @example Get the setter value.
|
|
100
|
+
# field.set("New Value")
|
|
101
|
+
#
|
|
102
|
+
# @param [ Object ] object The value to cast to a database value.
|
|
103
|
+
#
|
|
104
|
+
# @return [ Object ] The typecast value.
|
|
105
|
+
#
|
|
106
|
+
# @since 1.0.0
|
|
107
|
+
def set(object)
|
|
108
|
+
unless options[:identity]
|
|
109
|
+
type.set(object)
|
|
110
|
+
else
|
|
111
|
+
if object.blank?
|
|
112
|
+
type.set(object) if object.is_a?(Array)
|
|
113
|
+
else
|
|
114
|
+
options[:metadata].constraint.convert(object)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Used for retrieving the object out of the attributes hash.
|
|
120
|
+
#
|
|
121
|
+
# @example Get the value.
|
|
122
|
+
# field.get("Value")
|
|
123
|
+
#
|
|
124
|
+
# @param [ Object ] The object to cast from the database.
|
|
125
|
+
#
|
|
126
|
+
# @return [ Object ] The converted value.
|
|
127
|
+
#
|
|
128
|
+
# @since 1.0.0
|
|
129
|
+
def get(object)
|
|
130
|
+
type.get(object)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
protected
|
|
134
|
+
|
|
135
|
+
# Copy the default value if copyable.
|
|
136
|
+
#
|
|
137
|
+
# @example Copy the default.
|
|
138
|
+
# field.copy
|
|
139
|
+
#
|
|
140
|
+
# @return [ Object ] The copied object or the original.
|
|
141
|
+
#
|
|
142
|
+
# @since 1.0.0
|
|
143
|
+
def copy
|
|
144
|
+
copyable ? @default.dup : @default
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Checks if the default value is of the same type as the field.
|
|
148
|
+
#
|
|
149
|
+
# @example Check the default value.
|
|
150
|
+
# field.check_default!
|
|
151
|
+
#
|
|
152
|
+
# @raise [ Errors::InvalidType ] If the types differ.
|
|
153
|
+
#
|
|
154
|
+
# @since 1.0.0
|
|
155
|
+
def check_default!
|
|
156
|
+
return if @default.is_a?(Proc)
|
|
157
|
+
if !@default.nil? && !@default.is_a?(type)
|
|
158
|
+
raise Mongoid::Errors::InvalidType.new(type, @default)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc
|
|
3
|
+
|
|
4
|
+
# This module defines behaviour for fields.
|
|
5
|
+
module Fields
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
# Set up the class attributes that must be available to all subclasses.
|
|
10
|
+
# These include defaults, fields
|
|
11
|
+
delegate :defaults, :fields, :to => "self.class"
|
|
12
|
+
|
|
13
|
+
field(:_type, :type => String)
|
|
14
|
+
field(:_id, :type => BSON::ObjectId)
|
|
15
|
+
|
|
16
|
+
alias :id :_id
|
|
17
|
+
alias :id= :_id=
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module ClassMethods #:nodoc
|
|
21
|
+
|
|
22
|
+
# Defines all the fields that are accessible on the Document
|
|
23
|
+
# For each field that is defined, a getter and setter will be
|
|
24
|
+
# added as an instance method to the Document.
|
|
25
|
+
#
|
|
26
|
+
# @example Define a field.
|
|
27
|
+
# field :score, :type => Integer, :default => 0
|
|
28
|
+
#
|
|
29
|
+
# @param [ Symbol ] name The name of the field.
|
|
30
|
+
# @param [ Hash ] options The options to pass to the field.
|
|
31
|
+
#
|
|
32
|
+
# @option options [ Class ] :type The type of the field.
|
|
33
|
+
# @option options [ String ] :label The label for the field.
|
|
34
|
+
# @option options [ Object, Proc ] :default The field's default
|
|
35
|
+
#
|
|
36
|
+
# @return [ Field ] The generated field
|
|
37
|
+
def field(name, options = {})
|
|
38
|
+
access = name.to_s
|
|
39
|
+
set_field(access, options)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Return the fields for this class.
|
|
43
|
+
#
|
|
44
|
+
# @example Get the fields.
|
|
45
|
+
# Person.fields
|
|
46
|
+
#
|
|
47
|
+
# @return [ Hash ] The fields for this document.
|
|
48
|
+
#
|
|
49
|
+
# @since 2.0.0.rc.6
|
|
50
|
+
def fields
|
|
51
|
+
@fields ||= {}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Set the fields for the class.
|
|
55
|
+
#
|
|
56
|
+
# @example Set the fields.
|
|
57
|
+
# Person.fields = fields
|
|
58
|
+
#
|
|
59
|
+
# @param [ Hash ] fields The hash of fields to set.
|
|
60
|
+
#
|
|
61
|
+
# @since 2.0.0.rc.6
|
|
62
|
+
def fields=(fields)
|
|
63
|
+
@fields = fields
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Returns the default values for the fields on the document.
|
|
67
|
+
#
|
|
68
|
+
# @example Get the defaults.
|
|
69
|
+
# Person.defaults
|
|
70
|
+
#
|
|
71
|
+
# @return [ Hash ] The field defaults.
|
|
72
|
+
def defaults
|
|
73
|
+
fields.inject({}) do |defs, (field_name,field)|
|
|
74
|
+
next(defs) if field.default.nil?
|
|
75
|
+
defs[field_name.to_s] = field.default
|
|
76
|
+
defs
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# When inheriting, we want to copy the fields from the parent class and
|
|
81
|
+
# set the on the child to start, mimicking the behaviour of the old
|
|
82
|
+
# class_inheritable_accessor that was deprecated in Rails edge.
|
|
83
|
+
#
|
|
84
|
+
# @example Inherit from this class.
|
|
85
|
+
# Person.inherited(Doctor)
|
|
86
|
+
#
|
|
87
|
+
# @param [ Class ] subclass The inheriting class.
|
|
88
|
+
#
|
|
89
|
+
# @since 2.0.0.rc.6
|
|
90
|
+
def inherited(subclass)
|
|
91
|
+
super
|
|
92
|
+
subclass.fields = fields.dup
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
protected
|
|
96
|
+
|
|
97
|
+
# Define a field attribute for the +Document+.
|
|
98
|
+
#
|
|
99
|
+
# @example Set the field.
|
|
100
|
+
# Person.set_field(:name, :default => "Test")
|
|
101
|
+
#
|
|
102
|
+
# @param [ Symbol ] name The name of the field.
|
|
103
|
+
# @param [ Hash ] options The hash of options.
|
|
104
|
+
def set_field(name, options = {})
|
|
105
|
+
meth = options.delete(:as) || name
|
|
106
|
+
Field.new(name, options).tap do |field|
|
|
107
|
+
fields[name] = field
|
|
108
|
+
create_accessors(name, meth, options)
|
|
109
|
+
add_dirty_methods(name)
|
|
110
|
+
process_options(field)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Run through all custom options stored in Mongoid::Field.options and
|
|
115
|
+
# execute the handler if the option is provided.
|
|
116
|
+
#
|
|
117
|
+
# @example
|
|
118
|
+
# Mongoid::Field.option :custom do
|
|
119
|
+
# puts "called"
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# field = Mongoid::Field.new(:test, :custom => true)
|
|
123
|
+
# Person.process_options(field)
|
|
124
|
+
# # => "called"
|
|
125
|
+
#
|
|
126
|
+
# @param [ Field ] field the field to process
|
|
127
|
+
def process_options(field)
|
|
128
|
+
options = field.options
|
|
129
|
+
|
|
130
|
+
Field.options.each do |option_name, handler|
|
|
131
|
+
if options.has_key?(option_name)
|
|
132
|
+
handler.call(self, field, options[option_name])
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Create the field accessors.
|
|
138
|
+
#
|
|
139
|
+
# @example Generate the accessors.
|
|
140
|
+
# Person.create_accessors(:name, "name")
|
|
141
|
+
# person.name #=> returns the field
|
|
142
|
+
# person.name = "" #=> sets the field
|
|
143
|
+
# person.name? #=> Is the field present?
|
|
144
|
+
#
|
|
145
|
+
# @param [ Symbol ] name The name of the field.
|
|
146
|
+
# @param [ Symbol ] meth The name of the accessor.
|
|
147
|
+
# @param [ Hash ] options The options.
|
|
148
|
+
def create_accessors(name, meth, options = {})
|
|
149
|
+
field = fields[name]
|
|
150
|
+
generated_field_methods.module_eval do
|
|
151
|
+
if field.cast_on_read?
|
|
152
|
+
define_method(meth) do
|
|
153
|
+
field.get(read_attribute(name))
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
define_method(meth) do
|
|
157
|
+
read_attribute(name)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
define_method("#{meth}=") do |value|
|
|
161
|
+
write_attribute(name, value)
|
|
162
|
+
end
|
|
163
|
+
define_method("#{meth}?") do
|
|
164
|
+
attr = read_attribute(name)
|
|
165
|
+
(options[:type] == Boolean) ? attr == true : attr.present?
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Include the field methods as a module, so they can be overridden.
|
|
171
|
+
#
|
|
172
|
+
# @example Include the fields.
|
|
173
|
+
# Person.generated_field_methods
|
|
174
|
+
def generated_field_methods
|
|
175
|
+
@generated_field_methods ||= begin
|
|
176
|
+
Module.new.tap do |mod|
|
|
177
|
+
include mod
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|