mongoid 2.0.0.beta.20 → 2.0.0.rc.1
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/README.rdoc +8 -0
- data/Rakefile +51 -0
- data/lib/config/locales/nl.yml +39 -0
- data/lib/config/locales/ro.yml +1 -1
- data/lib/mongoid.rb +17 -17
- data/lib/mongoid/atomicity.rb +54 -22
- data/lib/mongoid/attributes.rb +145 -125
- data/lib/mongoid/callbacks.rb +7 -2
- data/lib/mongoid/collection.rb +49 -32
- data/lib/mongoid/collections.rb +0 -1
- data/lib/mongoid/components.rb +34 -29
- data/lib/mongoid/config.rb +207 -193
- data/lib/mongoid/config/database.rb +167 -0
- data/lib/mongoid/contexts.rb +2 -5
- data/lib/mongoid/contexts/enumerable.rb +30 -4
- data/lib/mongoid/contexts/ids.rb +2 -2
- data/lib/mongoid/contexts/mongo.rb +30 -5
- data/lib/mongoid/copyable.rb +44 -0
- data/lib/mongoid/criteria.rb +110 -56
- data/lib/mongoid/criterion/creational.rb +34 -0
- data/lib/mongoid/criterion/destructive.rb +37 -0
- data/lib/mongoid/criterion/exclusion.rb +3 -1
- data/lib/mongoid/criterion/inclusion.rb +59 -64
- data/lib/mongoid/criterion/inspection.rb +22 -0
- data/lib/mongoid/criterion/optional.rb +42 -54
- data/lib/mongoid/criterion/selector.rb +9 -0
- data/lib/mongoid/default_scope.rb +28 -0
- data/lib/mongoid/deprecation.rb +5 -5
- data/lib/mongoid/dirty.rb +4 -5
- data/lib/mongoid/document.rb +161 -114
- data/lib/mongoid/extensions.rb +7 -11
- data/lib/mongoid/extensions/array/parentization.rb +2 -2
- data/lib/mongoid/extensions/date/conversions.rb +1 -1
- data/lib/mongoid/extensions/hash/conversions.rb +0 -23
- data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
- data/lib/mongoid/extensions/object/reflections.rb +17 -0
- data/lib/mongoid/extensions/object/yoda.rb +27 -0
- data/lib/mongoid/extensions/string/conversions.rb +23 -4
- data/lib/mongoid/extensions/time_conversions.rb +4 -4
- data/lib/mongoid/field.rb +30 -19
- data/lib/mongoid/fields.rb +15 -5
- data/lib/mongoid/finders.rb +19 -11
- data/lib/mongoid/hierarchy.rb +34 -28
- data/lib/mongoid/identity.rb +62 -20
- data/lib/mongoid/inspection.rb +58 -0
- data/lib/mongoid/matchers.rb +20 -0
- data/lib/mongoid/multi_database.rb +11 -0
- data/lib/mongoid/nested_attributes.rb +41 -0
- data/lib/mongoid/paranoia.rb +3 -4
- data/lib/mongoid/paths.rb +1 -1
- data/lib/mongoid/persistence.rb +89 -90
- data/lib/mongoid/persistence/command.rb +20 -4
- data/lib/mongoid/persistence/insert.rb +13 -11
- data/lib/mongoid/persistence/insert_embedded.rb +8 -6
- data/lib/mongoid/persistence/remove.rb +6 -4
- data/lib/mongoid/persistence/remove_all.rb +6 -4
- data/lib/mongoid/persistence/remove_embedded.rb +8 -6
- data/lib/mongoid/persistence/update.rb +12 -10
- data/lib/mongoid/railtie.rb +2 -2
- data/lib/mongoid/railties/database.rake +10 -9
- data/lib/mongoid/relations.rb +104 -0
- data/lib/mongoid/relations/accessors.rb +154 -0
- data/lib/mongoid/relations/auto_save.rb +34 -0
- data/lib/mongoid/relations/binding.rb +24 -0
- data/lib/mongoid/relations/bindings.rb +9 -0
- data/lib/mongoid/relations/bindings/embedded/in.rb +77 -0
- data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
- data/lib/mongoid/relations/bindings/embedded/one.rb +65 -0
- data/lib/mongoid/relations/bindings/referenced/in.rb +78 -0
- data/lib/mongoid/relations/bindings/referenced/many.rb +93 -0
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +94 -0
- data/lib/mongoid/relations/bindings/referenced/one.rb +63 -0
- data/lib/mongoid/relations/builder.rb +41 -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 +116 -0
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
- data/lib/mongoid/relations/builders/referenced/in.rb +32 -0
- data/lib/mongoid/relations/builders/referenced/many.rb +26 -0
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
- data/lib/mongoid/relations/builders/referenced/one.rb +30 -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/cyclic.rb +97 -0
- data/lib/mongoid/relations/embedded/in.rb +172 -0
- data/lib/mongoid/relations/embedded/many.rb +450 -0
- data/lib/mongoid/relations/embedded/one.rb +169 -0
- data/lib/mongoid/relations/macros.rb +302 -0
- data/lib/mongoid/relations/many.rb +185 -0
- data/lib/mongoid/relations/metadata.rb +529 -0
- data/lib/mongoid/relations/nested_builder.rb +52 -0
- data/lib/mongoid/relations/one.rb +29 -0
- data/lib/mongoid/relations/polymorphic.rb +54 -0
- data/lib/mongoid/relations/proxy.rb +122 -0
- data/lib/mongoid/relations/referenced/in.rb +214 -0
- data/lib/mongoid/relations/referenced/many.rb +358 -0
- data/lib/mongoid/relations/referenced/many_to_many.rb +379 -0
- data/lib/mongoid/relations/referenced/one.rb +204 -0
- data/lib/mongoid/relations/reflections.rb +45 -0
- data/lib/mongoid/safe.rb +11 -1
- data/lib/mongoid/safety.rb +122 -97
- data/lib/mongoid/scope.rb +14 -9
- data/lib/mongoid/state.rb +37 -3
- data/lib/mongoid/timestamps.rb +11 -0
- data/lib/mongoid/validations.rb +42 -3
- data/lib/mongoid/validations/associated.rb +8 -5
- data/lib/mongoid/validations/uniqueness.rb +23 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +25 -16
- data/lib/rails/generators/mongoid/model/templates/model.rb +3 -1
- metadata +95 -80
- data/lib/mongoid/associations.rb +0 -364
- data/lib/mongoid/associations/embedded_in.rb +0 -74
- data/lib/mongoid/associations/embeds_many.rb +0 -299
- data/lib/mongoid/associations/embeds_one.rb +0 -111
- data/lib/mongoid/associations/foreign_key.rb +0 -35
- data/lib/mongoid/associations/meta_data.rb +0 -38
- data/lib/mongoid/associations/options.rb +0 -78
- data/lib/mongoid/associations/proxy.rb +0 -60
- data/lib/mongoid/associations/referenced_in.rb +0 -70
- data/lib/mongoid/associations/references_many.rb +0 -254
- data/lib/mongoid/associations/references_many_as_array.rb +0 -128
- data/lib/mongoid/associations/references_one.rb +0 -104
- data/lib/mongoid/extensions/array/accessors.rb +0 -17
- data/lib/mongoid/extensions/array/assimilation.rb +0 -26
- data/lib/mongoid/extensions/hash/accessors.rb +0 -42
- data/lib/mongoid/extensions/hash/assimilation.rb +0 -40
- data/lib/mongoid/extensions/nil/assimilation.rb +0 -17
- data/lib/mongoid/memoization.rb +0 -33
data/README.rdoc
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
= PLEASE READ (03 JAN 2011)
|
2
|
+
|
3
|
+
USERS CURRENTLY POINTED AT master, PLEASE MOVE TO safe_master UNTIL
|
4
|
+
FURTHER NOTICE.
|
5
|
+
|
1
6
|
= Overview
|
2
7
|
|
3
8
|
== About Mongoid
|
@@ -18,6 +23,9 @@ Mongoid is developed against Ruby 1.8.7, 1.9.1, 1.9.2, and REE.
|
|
18
23
|
Please see the new Mongoid website for up-to-date documentation:
|
19
24
|
{mongoid.org}[http://mongoid.org]
|
20
25
|
|
26
|
+
= Donating
|
27
|
+
* {Support Mongoid at Pledgie}[http://www.pledgie.com/campaigns/7757]
|
28
|
+
|
21
29
|
= License
|
22
30
|
|
23
31
|
Copyright (c) 2009, 2010 Durran Jordan
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
require "rake/rdoctask"
|
6
|
+
require "rspec"
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
10
|
+
require "mongoid/version"
|
11
|
+
|
12
|
+
task :gem => :build
|
13
|
+
task :build do
|
14
|
+
system "gem build mongoid.gemspec"
|
15
|
+
end
|
16
|
+
|
17
|
+
task :install => :build do
|
18
|
+
system "sudo gem install mongoid-#{Mongoid::VERSION}.gem"
|
19
|
+
end
|
20
|
+
|
21
|
+
task :release => :build do
|
22
|
+
system "git tag -a #{Mongoid::VERSION} -m 'Tagging #{Mongoid::VERSION}'"
|
23
|
+
system "git push --tags"
|
24
|
+
system "gem push mongoid-#{Mongoid::VERSION}.gem"
|
25
|
+
end
|
26
|
+
|
27
|
+
Rspec::Core::RakeTask.new(:spec) do |spec|
|
28
|
+
spec.pattern = "spec/**/*_spec.rb"
|
29
|
+
end
|
30
|
+
|
31
|
+
Rspec::Core::RakeTask.new("spec:unit") do |spec|
|
32
|
+
spec.pattern = "spec/unit/**/*_spec.rb"
|
33
|
+
end
|
34
|
+
|
35
|
+
Rspec::Core::RakeTask.new("spec:integration") do |spec|
|
36
|
+
spec.pattern = "spec/integration/**/*_spec.rb"
|
37
|
+
end
|
38
|
+
|
39
|
+
Rspec::Core::RakeTask.new('spec:progress') do |spec|
|
40
|
+
spec.rspec_opts = %w(--format progress)
|
41
|
+
spec.pattern = "spec/**/*_spec.rb"
|
42
|
+
end
|
43
|
+
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
rdoc.rdoc_dir = "rdoc"
|
46
|
+
rdoc.title = "mongoid #{Mongoid::VERSION}"
|
47
|
+
rdoc.rdoc_files.include("README*")
|
48
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
49
|
+
end
|
50
|
+
|
51
|
+
task :default => :spec
|
@@ -0,0 +1,39 @@
|
|
1
|
+
nl:
|
2
|
+
activemodel:
|
3
|
+
errors:
|
4
|
+
messages:
|
5
|
+
taken: al in gebruik
|
6
|
+
|
7
|
+
mongoid:
|
8
|
+
errors:
|
9
|
+
messages:
|
10
|
+
document_not_found:
|
11
|
+
Document niet gevonden voor class %{klass} met de id(s) %{identifiers}.
|
12
|
+
invalid_database:
|
13
|
+
Database moet een Mongo::DB zijn, niet een %{name}.
|
14
|
+
invalid_type:
|
15
|
+
Veld was gedefinieerd als een %{klass}, maar ontvangen als %{other} met
|
16
|
+
de waarde %{value}.
|
17
|
+
unsupported_version:
|
18
|
+
MongoDB %{version} wordt niet ondersteund, upgrade naar versie %{mongo_version}.
|
19
|
+
validations:
|
20
|
+
Gefaalde validatie - %{errors}.
|
21
|
+
invalid_collection:
|
22
|
+
Toegang tot de collectie voor %{klass} is niet toegestaan aangezien het
|
23
|
+
een embedded document is, benader de collectie van een root document.
|
24
|
+
invalid_field:
|
25
|
+
Het is niet toegestaan om een veld genaamd %{name} te definiëren.
|
26
|
+
Definieer geen velden die conflicteren met de Mongoid interne attributen of methode namen.
|
27
|
+
Gerbuik Document#instance_methods om welke namen dit gaat.
|
28
|
+
too_many_nested_attribute_records:
|
29
|
+
Het accepteren van nested attributes voor %{association} is gelimiteerd tot %{limit} records.
|
30
|
+
embedded_in_must_have_inverse_of:
|
31
|
+
Opties voor embedded_in association moet gebruik maken van de inverse_of optie.
|
32
|
+
dependent_only_references_one_or_many:
|
33
|
+
De dependent => destroy|delete optie die was meegegeven is alleen geldig
|
34
|
+
op references_one en references_many associations.
|
35
|
+
association_cant_have_inverse_of:
|
36
|
+
Het definieren van een inverse_of op deze association is niet toegestaan. Gebruik
|
37
|
+
alleen deze optie met embedded_in en references_many as array.
|
38
|
+
calling_document_find_with_nil_is_invalid:
|
39
|
+
Het is niet toegestaan om Document#find aan te roepen met de waarde nil.
|
data/lib/config/locales/ro.yml
CHANGED
data/lib/mongoid.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
# Copyright (c) 2009, 2010 Durran Jordan
|
3
4
|
#
|
4
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
@@ -19,9 +20,7 @@
|
|
19
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
|
23
23
|
require "delegate"
|
24
|
-
require "singleton"
|
25
24
|
require "time"
|
26
25
|
require "ostruct"
|
27
26
|
require "active_support/core_ext"
|
@@ -43,7 +42,6 @@ require "mongo"
|
|
43
42
|
require "mongoid/errors"
|
44
43
|
require "mongoid/extensions"
|
45
44
|
require "mongoid/safe"
|
46
|
-
require "mongoid/associations"
|
47
45
|
require "mongoid/atomicity"
|
48
46
|
require "mongoid/attributes"
|
49
47
|
require "mongoid/callbacks"
|
@@ -51,9 +49,11 @@ require "mongoid/collection"
|
|
51
49
|
require "mongoid/collections"
|
52
50
|
require "mongoid/config"
|
53
51
|
require "mongoid/contexts"
|
52
|
+
require "mongoid/copyable"
|
54
53
|
require "mongoid/criteria"
|
55
54
|
require "mongoid/cursor"
|
56
55
|
require "mongoid/deprecation"
|
56
|
+
require "mongoid/default_scope"
|
57
57
|
require "mongoid/dirty"
|
58
58
|
require "mongoid/extras"
|
59
59
|
require "mongoid/factory"
|
@@ -63,17 +63,20 @@ require "mongoid/finders"
|
|
63
63
|
require "mongoid/hierarchy"
|
64
64
|
require "mongoid/identity"
|
65
65
|
require "mongoid/indexes"
|
66
|
+
require "mongoid/inspection"
|
66
67
|
require "mongoid/javascript"
|
67
68
|
require "mongoid/json"
|
68
69
|
require "mongoid/keys"
|
69
70
|
require "mongoid/logger"
|
70
71
|
require "mongoid/matchers"
|
71
|
-
require "mongoid/memoization"
|
72
72
|
require "mongoid/modifiers"
|
73
73
|
require "mongoid/multi_parameter_attributes"
|
74
|
+
require "mongoid/multi_database"
|
74
75
|
require "mongoid/named_scope"
|
76
|
+
require "mongoid/nested_attributes"
|
75
77
|
require "mongoid/paths"
|
76
78
|
require "mongoid/persistence"
|
79
|
+
require "mongoid/relations"
|
77
80
|
require "mongoid/safety"
|
78
81
|
require "mongoid/scope"
|
79
82
|
require "mongoid/state"
|
@@ -100,7 +103,7 @@ module Mongoid #:nodoc
|
|
100
103
|
|
101
104
|
# Sets the Mongoid configuration options. Best used by passing a block.
|
102
105
|
#
|
103
|
-
#
|
106
|
+
# @example Set up configuration options.
|
104
107
|
#
|
105
108
|
# Mongoid.configure do |config|
|
106
109
|
# name = "mongoid_test"
|
@@ -113,33 +116,30 @@ module Mongoid #:nodoc
|
|
113
116
|
# ]
|
114
117
|
# end
|
115
118
|
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# The Mongoid +Config+ singleton instance.
|
119
|
+
# @return [ Config ] The configuration obejct.
|
119
120
|
def configure
|
120
|
-
config = Mongoid::Config
|
121
|
+
config = Mongoid::Config
|
121
122
|
block_given? ? yield(config) : config
|
122
123
|
end
|
124
|
+
alias :config :configure
|
123
125
|
|
124
126
|
# Easy convenience method for generating an alert from the
|
125
127
|
# deprecation module.
|
126
128
|
#
|
127
|
-
#
|
129
|
+
# @example Alert a deprecation.
|
130
|
+
# Mongoid.deprecate("Method no longer used")
|
128
131
|
#
|
129
|
-
#
|
132
|
+
# @param [ String ] message The message to print.
|
130
133
|
def deprecate(message)
|
131
|
-
Mongoid::Deprecation.
|
134
|
+
Mongoid::Deprecation.alert(message)
|
132
135
|
end
|
133
|
-
|
134
|
-
alias :config :configure
|
135
136
|
end
|
136
137
|
|
137
138
|
# Take all the public instance methods from the Config singleton and allow
|
138
139
|
# them to be accessed through the Mongoid module directly.
|
139
140
|
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
# <tt>Mongoid.database = Mongo::Connection.new.db("test")</tt>
|
141
|
+
# @example Delegate the configuration methods.
|
142
|
+
# Mongoid.database = Mongo::Connection.new.db("test")
|
143
143
|
Mongoid::Config.public_instance_methods(false).each do |name|
|
144
144
|
(class << self; self; end).class_eval <<-EOT
|
145
145
|
def #{name}(*args)
|
data/lib/mongoid/atomicity.rb
CHANGED
@@ -1,46 +1,52 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
|
-
|
3
|
+
|
4
|
+
# This module contains the logic for supporting atomic operations against the
|
5
|
+
# database.
|
6
|
+
#
|
7
|
+
# @todo Durran: Refactor class out into separate objects for each type of
|
8
|
+
# update.
|
9
|
+
module Atomicity
|
4
10
|
extend ActiveSupport::Concern
|
5
11
|
|
6
12
|
# Get all the atomic updates that need to happen for the current
|
7
13
|
# +Document+. This includes all changes that need to happen in the
|
8
14
|
# entire hierarchy that exists below where the save call was made.
|
9
15
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
16
|
+
# @note
|
17
|
+
# MongoDB does not allow "conflicting modifications" to be
|
18
|
+
# performed in a single operation. Conflicting modifications are
|
19
|
+
# detected by the 'haveConflictingMod' function in MongoDB.
|
20
|
+
# Examination of the code suggests that two modifications (a $set
|
21
|
+
# and a $pushAll, for example) conflict if:
|
22
|
+
# (1) the key paths being modified are equal.
|
23
|
+
# (2) one key path is a prefix of the other.
|
24
|
+
# So a $set of 'addresses.0.street' will conflict with a $pushAll
|
25
|
+
# to 'addresses', and we will need to split our update into two
|
26
|
+
# pieces. We do not, however, attempt to match MongoDB's logic
|
27
|
+
# exactly. Instead, we assume that two updates conflict if the
|
28
|
+
# first component of the two key paths matches.
|
13
29
|
#
|
14
|
-
#
|
30
|
+
# @example Get the updates that need to occur.
|
31
|
+
# person._updates
|
15
32
|
#
|
16
|
-
#
|
33
|
+
# @return [ Hash ] The updates and their modifiers.
|
17
34
|
def _updates
|
18
35
|
processed = {}
|
19
|
-
|
36
|
+
|
20
37
|
_children.inject({ "$set" => _sets, "$pushAll" => {}, :other => {} }) do |updates, child|
|
21
38
|
changes = child._sets
|
22
39
|
updates["$set"].update(changes)
|
23
40
|
unless changes.empty?
|
24
41
|
processed[child._conficting_modification_key] = true
|
25
42
|
end
|
26
|
-
|
27
|
-
# MongoDB does not allow "conflicting modifications" to be
|
28
|
-
# performed in a single operation. Conflicting modifications are
|
29
|
-
# detected by the 'haveConflictingMod' function in MongoDB.
|
30
|
-
# Examination of the code suggests that two modifications (a $set
|
31
|
-
# and a $pushAll, for example) conflict if (1) the key paths being
|
32
|
-
# modified are equal or (2) one key path is a prefix of the other.
|
33
|
-
# So a $set of 'addresses.0.street' will conflict with a $pushAll
|
34
|
-
# to 'addresses', and we will need to split our update into two
|
35
|
-
# pieces. We do not, however, attempt to match MongoDB's logic
|
36
|
-
# exactly. Instead, we assume that two updates conflict if the
|
37
|
-
# first component of the two key paths matches.
|
43
|
+
|
38
44
|
if processed.has_key?(child._conficting_modification_key)
|
39
45
|
target = :other
|
40
46
|
else
|
41
47
|
target = "$pushAll"
|
42
48
|
end
|
43
|
-
|
49
|
+
|
44
50
|
child._pushes.each do |attr, val|
|
45
51
|
if updates[target].has_key?(attr)
|
46
52
|
updates[target][attr] << val
|
@@ -55,24 +61,50 @@ module Mongoid #:nodoc:
|
|
55
61
|
end
|
56
62
|
|
57
63
|
protected
|
64
|
+
|
58
65
|
# Get the key used to check for conflicting modifications. For now, we
|
59
66
|
# just use the first component of _path, and discard the first period
|
60
67
|
# and everything that follows.
|
68
|
+
#
|
69
|
+
# @example Get the key.
|
70
|
+
# person._conflicting_modification_key
|
71
|
+
#
|
72
|
+
# @return [ String ] The conflicting key.
|
61
73
|
def _conficting_modification_key
|
62
74
|
_path.sub(/\..*/, '')
|
63
75
|
end
|
64
76
|
|
65
77
|
# Get all the push attributes that need to occur.
|
78
|
+
#
|
79
|
+
# @example Get the pushes.
|
80
|
+
# person._pushes
|
81
|
+
#
|
82
|
+
# @return [ Hash ] The $pushAll operations.
|
66
83
|
def _pushes
|
67
|
-
|
84
|
+
pushable? ? { _path => to_hash } : {}
|
85
|
+
end
|
86
|
+
|
87
|
+
# Determine if the document can be pushed.
|
88
|
+
#
|
89
|
+
# @example Is this pushable?
|
90
|
+
# person.pushable?
|
91
|
+
#
|
92
|
+
# @return [ true, false ] Is the document new and embedded?
|
93
|
+
def pushable?
|
94
|
+
new_record? && embedded_many? && _parent.persisted?
|
68
95
|
end
|
69
96
|
|
70
97
|
# Get all the attributes that need to be set.
|
98
|
+
#
|
99
|
+
# @example Get the sets.
|
100
|
+
# person._sets
|
101
|
+
#
|
102
|
+
# @return [ Hash ] The $set operations.
|
71
103
|
def _sets
|
72
104
|
if changed? && !new_record?
|
73
105
|
setters
|
74
106
|
else
|
75
|
-
embedded_one? && new_record? ? { _path =>
|
107
|
+
embedded_one? && new_record? ? { _path => to_hash } : {}
|
76
108
|
end
|
77
109
|
end
|
78
110
|
end
|
data/lib/mongoid/attributes.rb
CHANGED
@@ -1,23 +1,75 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
|
+
|
4
|
+
# This module contains the logic for handling the internal attributes hash,
|
5
|
+
# and how to get and set values.
|
3
6
|
module Attributes
|
4
|
-
|
7
|
+
|
8
|
+
# Returns the object type. This corresponds to the name of the class that
|
9
|
+
# this document is, which is used in determining the class to
|
10
|
+
# instantiate in various cases.
|
11
|
+
#
|
12
|
+
# @example Get the type.
|
13
|
+
# person._type
|
14
|
+
#
|
15
|
+
# @return [ String ] The name of the class the document is.
|
16
|
+
def _type
|
17
|
+
@attributes["_type"]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Set the type of the document. This should be the name of the class.
|
21
|
+
#
|
22
|
+
# @example Set the type
|
23
|
+
# person._type = "Person"
|
24
|
+
#
|
25
|
+
# @param [ String ] new_type The name of the class.
|
26
|
+
#
|
27
|
+
# @return [ String ] the new type.
|
28
|
+
def _type=(new_type)
|
29
|
+
@attributes["_type"] = new_type
|
30
|
+
end
|
31
|
+
|
32
|
+
# Determine if an attribute is present.
|
33
|
+
#
|
34
|
+
# @example Is the attribute present?
|
35
|
+
# person.attribute_present?("title")
|
36
|
+
#
|
37
|
+
# @param [ String, Symbol ] name The name of the attribute.
|
38
|
+
#
|
39
|
+
# @return [ true, false ] True if present, false if not.
|
40
|
+
def attribute_present?(name)
|
41
|
+
!read_attribute(name).blank?
|
42
|
+
end
|
5
43
|
|
6
44
|
# Get the id associated with this object. This will pull the _id value out
|
7
|
-
# of the attributes
|
45
|
+
# of the attributes.
|
46
|
+
#
|
47
|
+
# @example Get the id.
|
48
|
+
# person.id
|
49
|
+
#
|
50
|
+
# @return [ BSON::ObjectId, String ] The id of the document.
|
8
51
|
def id
|
9
52
|
@attributes["_id"]
|
10
53
|
end
|
54
|
+
alias :_id :id
|
11
55
|
|
12
|
-
# Set the id of the
|
56
|
+
# Set the id of the document to a new one.
|
57
|
+
#
|
58
|
+
# @example Set the id.
|
59
|
+
# person.id = BSON::ObjectId.new
|
60
|
+
#
|
61
|
+
# @param [ BSON::ObjectId, String ] new_id The new id.
|
62
|
+
#
|
63
|
+
# @return [ BSON::ObjectId, String ] The new id.
|
13
64
|
def id=(new_id)
|
14
65
|
@attributes["_id"] = new_id
|
15
66
|
end
|
16
|
-
|
17
|
-
alias :_id :id
|
18
67
|
alias :_id= :id=
|
19
68
|
|
20
69
|
# Used for allowing accessor methods for dynamic attributes.
|
70
|
+
#
|
71
|
+
# @param [ String, Symbol ] name The name of the method.
|
72
|
+
# @param [ Array ] *args The arguments to the method.
|
21
73
|
def method_missing(name, *args)
|
22
74
|
attr = name.to_s
|
23
75
|
return super unless @attributes.has_key?(attr.reader)
|
@@ -29,44 +81,42 @@ module Mongoid #:nodoc:
|
|
29
81
|
end
|
30
82
|
end
|
31
83
|
|
32
|
-
# Override respond_to? so it responds properly for dynamic attributes
|
33
|
-
def respond_to?(*args)
|
34
|
-
(Mongoid.allow_dynamic_fields && @attributes && @attributes.has_key?(args.first.to_s)) || super
|
35
|
-
end
|
36
|
-
|
37
84
|
# Process the provided attributes casting them to their proper values if a
|
38
|
-
# field exists for them on the
|
85
|
+
# field exists for them on the document. This will be limited to only the
|
39
86
|
# attributes provided in the suppied +Hash+ so that no extra nil values get
|
40
87
|
# put into the document's attributes.
|
88
|
+
#
|
89
|
+
# @example Process the attributes.
|
90
|
+
# person.process(:title => "sir", :age => 40)
|
91
|
+
#
|
92
|
+
# @param [ Hash ] attrs The attributes to set.
|
41
93
|
def process(attrs = nil)
|
94
|
+
pending = {}
|
42
95
|
sanitize_for_mass_assignment(attrs || {}).each_pair do |key, value|
|
43
96
|
if set_allowed?(key)
|
44
97
|
write_attribute(key, value)
|
45
98
|
else
|
46
|
-
|
47
|
-
|
48
|
-
association.nested_build(value)
|
49
|
-
else
|
50
|
-
send("build_#{key}", value)
|
51
|
-
end
|
52
|
-
else
|
53
|
-
send("#{key}=", value)
|
54
|
-
end
|
99
|
+
pending[key.to_s] = value and next if relations.has_key?(key.to_s)
|
100
|
+
send("#{key}=", value)
|
55
101
|
end
|
56
102
|
end
|
103
|
+
yield self if block_given?
|
104
|
+
process_relations(pending)
|
57
105
|
setup_modifications
|
58
106
|
end
|
59
107
|
|
60
|
-
# Read a value from the
|
108
|
+
# Read a value from the document attributes. If the value does not exist
|
61
109
|
# it will return nil.
|
62
110
|
#
|
63
|
-
#
|
111
|
+
# @example Read an attribute.
|
112
|
+
# person.read_attribute(:title)
|
64
113
|
#
|
65
|
-
#
|
114
|
+
# @example Read an attribute (alternate syntax.)
|
115
|
+
# person[:title]
|
66
116
|
#
|
67
|
-
#
|
117
|
+
# @param [ String, Symbol ] name The name of the attribute to get.
|
68
118
|
#
|
69
|
-
#
|
119
|
+
# @return [ Object ] The value of the attribute.
|
70
120
|
def read_attribute(name)
|
71
121
|
access = name.to_s
|
72
122
|
value = @attributes[access]
|
@@ -78,93 +128,75 @@ module Mongoid #:nodoc:
|
|
78
128
|
# Remove a value from the +Document+ attributes. If the value does not exist
|
79
129
|
# it will fail gracefully.
|
80
130
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# name: The name of the attribute to remove.
|
131
|
+
# @example Remove the attribute.
|
132
|
+
# person.remove_attribute(:title)
|
84
133
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
# <tt>person.remove_attribute(:title)</tt>
|
134
|
+
# @param [ String, Symbol ] name The name of the attribute to remove.
|
88
135
|
def remove_attribute(name)
|
89
136
|
access = name.to_s
|
90
137
|
modify(access, @attributes.delete(name.to_s), nil)
|
91
138
|
end
|
92
139
|
|
93
|
-
#
|
140
|
+
# Override respond_to? so it responds properly for dynamic attributes.
|
94
141
|
#
|
95
|
-
#
|
142
|
+
# @example Does this object respond to the method?
|
143
|
+
# person.respond_to?(:title)
|
96
144
|
#
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
# instantiate in various cases.
|
106
|
-
def _type
|
107
|
-
@attributes["_type"]
|
108
|
-
end
|
109
|
-
|
110
|
-
# Set the type of the +Document+. This should be the name of the class.
|
111
|
-
def _type=(new_type)
|
112
|
-
@attributes["_type"] = new_type
|
145
|
+
# @param [ Array ] *args The name of the method.
|
146
|
+
#
|
147
|
+
# @return [ true, false ] True if it does, false if not.
|
148
|
+
def respond_to?(*args)
|
149
|
+
(Mongoid.allow_dynamic_fields &&
|
150
|
+
@attributes &&
|
151
|
+
@attributes.has_key?(args.first.to_s)
|
152
|
+
) || super
|
113
153
|
end
|
114
154
|
|
115
|
-
# Write a single attribute to the
|
155
|
+
# Write a single attribute to the document attribute hash. This will
|
116
156
|
# also fire the before and after update callbacks, and perform any
|
117
157
|
# necessary typecasting.
|
118
158
|
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
# name: The name of the attribute to update.
|
122
|
-
# value: The value to set for the attribute.
|
123
|
-
#
|
124
|
-
# Example:
|
159
|
+
# @example Write the attribute.
|
160
|
+
# person.write_attribute(:title, "Mr.")
|
125
161
|
#
|
126
|
-
#
|
162
|
+
# @example Write the attribute (alternate syntax.)
|
163
|
+
# person[:title] = "Mr."
|
127
164
|
#
|
128
|
-
#
|
129
|
-
#
|
165
|
+
# @param [ String, Symbol ] name The name of the attribute to update.
|
166
|
+
# @param [ Object ] value The value to set for the attribute.
|
130
167
|
def write_attribute(name, value)
|
131
168
|
access = name.to_s
|
132
169
|
modify(access, @attributes[access], typed_value_for(access, value))
|
133
|
-
notify if !id.blank? && new_record?
|
134
170
|
end
|
135
171
|
alias :[]= :write_attribute
|
136
172
|
|
137
|
-
# Writes the supplied attributes
|
173
|
+
# Writes the supplied attributes hash to the document. This will only
|
138
174
|
# overwrite existing attributes if they are present in the new +Hash+, all
|
139
175
|
# others will be preserved.
|
140
176
|
#
|
141
|
-
#
|
177
|
+
# @example Write the attributes.
|
178
|
+
# person.write_attributes(:title => "Mr.")
|
142
179
|
#
|
143
|
-
#
|
180
|
+
# @example Write the attributes (alternate syntax.)
|
181
|
+
# person.attributes = { :title => "Mr." }
|
144
182
|
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
# <tt>person.write_attributes(:title => "Mr.")</tt>
|
148
|
-
#
|
149
|
-
# This will also cause the observing +Document+ to notify it's parent if
|
150
|
-
# there is any.
|
183
|
+
# @param [ Hash ] attrs The new attributes to set.
|
151
184
|
def write_attributes(attrs = nil)
|
152
185
|
process(attrs || {})
|
153
|
-
|
154
|
-
|
155
|
-
identify; notify
|
186
|
+
if new_record? && id.blank?
|
187
|
+
identify
|
156
188
|
end
|
157
189
|
end
|
158
190
|
alias :attributes= :write_attributes
|
159
191
|
|
160
192
|
protected
|
161
193
|
|
162
|
-
#
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
#
|
194
|
+
# Get the default values for the attributes.
|
195
|
+
#
|
196
|
+
# @example Get the defaults.
|
197
|
+
# person.default_attributes
|
198
|
+
#
|
199
|
+
# @return [ Hash ] The default values for each field.
|
168
200
|
def default_attributes
|
169
201
|
default_values = defaults
|
170
202
|
default_values.each_pair do |key, val|
|
@@ -173,59 +205,47 @@ module Mongoid #:nodoc:
|
|
173
205
|
default_values || {}
|
174
206
|
end
|
175
207
|
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
#
|
182
|
-
#
|
183
|
-
def
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
208
|
+
# Process all the pending relations that needed to wait until ids were set
|
209
|
+
# to fire off.
|
210
|
+
#
|
211
|
+
# @example Process the relations.
|
212
|
+
# document.process_relations({ "addressable" => person })
|
213
|
+
#
|
214
|
+
# @param [ Hash ] pending The pending relation values.
|
215
|
+
def process_relations(pending)
|
216
|
+
pending.each_pair do |name, value|
|
217
|
+
metadata = relations[name]
|
218
|
+
if value.is_a?(Hash)
|
219
|
+
metadata.nested_builder(value, {}).build(self)
|
220
|
+
else
|
221
|
+
send("#{name}=", value)
|
188
222
|
end
|
189
223
|
end
|
190
224
|
end
|
191
225
|
|
192
|
-
#
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
226
|
+
# Return true if dynamic field setting is enabled.
|
227
|
+
#
|
228
|
+
# @example Is a set allowed for this name?
|
229
|
+
# person.set_allowed?(:title)
|
230
|
+
#
|
231
|
+
# @param [ String, Symbol ] key The name of the field.
|
232
|
+
#
|
233
|
+
# @return [ true, false ] True if allowed, false if not.
|
234
|
+
def set_allowed?(key)
|
235
|
+
Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
|
197
236
|
end
|
198
237
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# accepts_nested_attributes_for :name, :addresses
|
211
|
-
# end
|
212
|
-
def accepts_nested_attributes_for(*args)
|
213
|
-
associations = args.flatten
|
214
|
-
options = associations.last.is_a?(Hash) ? associations.pop : {}
|
215
|
-
associations.each do |name|
|
216
|
-
define_method("#{name}_attributes=") do |attrs|
|
217
|
-
reject(attrs, options)
|
218
|
-
limit(attrs, name, options)
|
219
|
-
association = send(name)
|
220
|
-
if association
|
221
|
-
# observe(association, true)
|
222
|
-
association.nested_build(attrs, options)
|
223
|
-
else
|
224
|
-
send("build_#{name}", attrs, options)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
238
|
+
# Return the typecasted value for a field.
|
239
|
+
#
|
240
|
+
# @example Get the value typecasted.
|
241
|
+
# person.typed_value_for(:title, :sir)
|
242
|
+
#
|
243
|
+
# @param [ String, Symbol ] key The field name.
|
244
|
+
# @param [ Object ] value The uncast value.
|
245
|
+
#
|
246
|
+
# @return [ Object ] The cast value.
|
247
|
+
def typed_value_for(key, value)
|
248
|
+
fields.has_key?(key) ? fields[key].set(value) : value
|
229
249
|
end
|
230
250
|
end
|
231
251
|
end
|