activerecord 4.2.11.3 → 5.0.7.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1638 -1132
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record.rb +7 -2
- data/lib/active_record/aggregations.rb +34 -21
- data/lib/active_record/association_relation.rb +7 -4
- data/lib/active_record/associations.rb +347 -218
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +22 -10
- data/lib/active_record/associations/association_scope.rb +75 -104
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +13 -11
- data/lib/active_record/associations/collection_association.rb +85 -69
- data/lib/active_record/associations/collection_proxy.rb +104 -46
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +21 -78
- data/lib/active_record/associations/has_many_through_association.rb +6 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +38 -22
- data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/preloader/association.rb +52 -71
- data/lib/active_record/associations/preloader/collection_association.rb +0 -7
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/singular_association.rb +0 -1
- data/lib/active_record/associations/preloader/through_association.rb +36 -17
- data/lib/active_record/associations/singular_association.rb +13 -1
- data/lib/active_record/associations/through_association.rb +12 -4
- data/lib/active_record/attribute.rb +69 -19
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +69 -44
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +16 -3
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +13 -37
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +32 -3
- data/lib/active_record/attribute_set/builder.rb +42 -16
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +54 -17
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
- data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +92 -108
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +116 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain.rb +20 -9
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +77 -41
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +17 -14
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +48 -24
- data/lib/active_record/migration.rb +362 -111
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/model_schema.rb +270 -73
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/no_touching.rb +4 -0
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +152 -90
- data/lib/active_record/query_cache.rb +18 -23
- data/lib/active_record/querying.rb +12 -11
- data/lib/active_record/railtie.rb +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +52 -41
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +302 -115
- data/lib/active_record/relation.rb +187 -120
- data/lib/active_record/relation/batches.rb +141 -36
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +92 -117
- data/lib/active_record/relation/delegation.rb +8 -20
- data/lib/active_record/relation/finder_methods.rb +173 -89
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/result.rb +11 -4
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +105 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +54 -37
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping.rb +34 -16
- data/lib/active_record/scoping/default.rb +28 -10
- data/lib/active_record/scoping/named.rb +59 -26
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +3 -5
- data/lib/active_record/statement_cache.rb +17 -15
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +69 -0
- data/lib/active_record/tasks/database_tasks.rb +66 -49
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +63 -0
- data/lib/active_record/transactions.rb +139 -57
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +33 -33
- data/lib/rails/generators/active_record/migration.rb +15 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +58 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2004-
|
1
|
+
Copyright (c) 2004-2016 David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -26,13 +26,13 @@ The Product class is automatically mapped to the table named "products",
|
|
26
26
|
which might look like this:
|
27
27
|
|
28
28
|
CREATE TABLE products (
|
29
|
-
id int
|
29
|
+
id int NOT NULL auto_increment,
|
30
30
|
name varchar(255),
|
31
31
|
PRIMARY KEY (id)
|
32
32
|
);
|
33
33
|
|
34
|
-
This would also define the following accessors:
|
35
|
-
|
34
|
+
This would also define the following accessors: <tt>Product#name</tt> and
|
35
|
+
<tt>Product#name=(new_name)</tt>.
|
36
36
|
|
37
37
|
|
38
38
|
* Associations between objects defined by simple class methods.
|
@@ -125,7 +125,7 @@ This would also define the following accessors: `Product#name` and
|
|
125
125
|
)
|
126
126
|
|
127
127
|
{Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
|
128
|
-
MySQL[link:classes/ActiveRecord/ConnectionAdapters/
|
128
|
+
MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
|
129
129
|
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
130
130
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
131
131
|
|
@@ -138,7 +138,7 @@ This would also define the following accessors: `Product#name` and
|
|
138
138
|
|
139
139
|
* Database agnostic schema management with Migrations.
|
140
140
|
|
141
|
-
class AddSystemSettings < ActiveRecord::Migration
|
141
|
+
class AddSystemSettings < ActiveRecord::Migration[5.0]
|
142
142
|
def up
|
143
143
|
create_table :system_settings do |t|
|
144
144
|
t.string :name
|
@@ -188,11 +188,11 @@ Admit the Database:
|
|
188
188
|
|
189
189
|
The latest version of Active Record can be installed with RubyGems:
|
190
190
|
|
191
|
-
|
191
|
+
$ gem install activerecord
|
192
192
|
|
193
193
|
Source code can be downloaded as part of the Rails project on GitHub:
|
194
194
|
|
195
|
-
* https://github.com/rails/rails/tree/
|
195
|
+
* https://github.com/rails/rails/tree/5-0-stable/activerecord
|
196
196
|
|
197
197
|
|
198
198
|
== License
|
@@ -215,4 +215,3 @@ Bug reports can be filed for the Ruby on Rails project here:
|
|
215
215
|
Feature requests should be discussed on the rails-core mailing list here:
|
216
216
|
|
217
217
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
218
|
-
|
data/examples/performance.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require File.expand_path('../../../load_paths', __FILE__)
|
2
1
|
require "active_record"
|
3
2
|
require 'benchmark/ips'
|
4
3
|
|
@@ -39,8 +38,8 @@ class Exhibit < ActiveRecord::Base
|
|
39
38
|
where("notes IS NOT NULL")
|
40
39
|
end
|
41
40
|
|
42
|
-
def self.look(exhibits) exhibits.each
|
43
|
-
def self.feel(exhibits) exhibits.each
|
41
|
+
def self.look(exhibits) exhibits.each(&:look) end
|
42
|
+
def self.feel(exhibits) exhibits.each(&:feel) end
|
44
43
|
end
|
45
44
|
|
46
45
|
def progress_bar(int); print "." if (int%100).zero? ; end
|
data/examples/simple.rb
CHANGED
data/lib/active_record.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2004-
|
2
|
+
# Copyright (c) 2004-2016 David Heinemeier Hansson
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -40,6 +40,7 @@ module ActiveRecord
|
|
40
40
|
autoload :CounterCache
|
41
41
|
autoload :DynamicMatchers
|
42
42
|
autoload :Enum
|
43
|
+
autoload :InternalMetadata
|
43
44
|
autoload :Explain
|
44
45
|
autoload :Inheritance
|
45
46
|
autoload :Integration
|
@@ -48,9 +49,11 @@ module ActiveRecord
|
|
48
49
|
autoload :ModelSchema
|
49
50
|
autoload :NestedAttributes
|
50
51
|
autoload :NoTouching
|
52
|
+
autoload :TouchLater
|
51
53
|
autoload :Persistence
|
52
54
|
autoload :QueryCache
|
53
55
|
autoload :Querying
|
56
|
+
autoload :CollectionCacheKey
|
54
57
|
autoload :ReadonlyAttributes
|
55
58
|
autoload :RecordInvalid, 'active_record/validations'
|
56
59
|
autoload :Reflection
|
@@ -63,10 +66,12 @@ module ActiveRecord
|
|
63
66
|
autoload :Serialization
|
64
67
|
autoload :StatementCache
|
65
68
|
autoload :Store
|
69
|
+
autoload :Suppressor
|
66
70
|
autoload :Timestamp
|
67
71
|
autoload :Transactions
|
68
72
|
autoload :Translation
|
69
73
|
autoload :Validations
|
74
|
+
autoload :SecureToken
|
70
75
|
|
71
76
|
eager_autoload do
|
72
77
|
autoload :ActiveRecordError, 'active_record/errors'
|
@@ -96,6 +101,7 @@ module ActiveRecord
|
|
96
101
|
end
|
97
102
|
|
98
103
|
autoload :Result
|
104
|
+
autoload :TableMetadata
|
99
105
|
end
|
100
106
|
|
101
107
|
module Coders
|
@@ -132,7 +138,6 @@ module ActiveRecord
|
|
132
138
|
|
133
139
|
eager_autoload do
|
134
140
|
autoload :AbstractAdapter
|
135
|
-
autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
|
136
141
|
end
|
137
142
|
end
|
138
143
|
|
@@ -1,14 +1,31 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
#
|
3
|
-
module Aggregations
|
2
|
+
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
3
|
+
module Aggregations
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
def
|
7
|
-
@aggregation_cache
|
6
|
+
def initialize_dup(*) # :nodoc:
|
7
|
+
@aggregation_cache = {}
|
8
|
+
super
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def reload(*) # :nodoc:
|
12
|
+
clear_aggregation_cache
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def clear_aggregation_cache # :nodoc:
|
19
|
+
@aggregation_cache.clear if persisted?
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_internals # :nodoc:
|
23
|
+
@aggregation_cache = {}
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
# Active Record implements aggregation through a macro-like class method called #composed_of
|
28
|
+
# for representing attributes as value objects. It expresses relationships like "Account [is]
|
12
29
|
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
|
13
30
|
# to the macro adds a description of how the value objects are created from the attributes of
|
14
31
|
# the entity object (when the entity is initialized either as a new object or from finding an
|
@@ -16,7 +33,7 @@ module ActiveRecord
|
|
16
33
|
# the database).
|
17
34
|
#
|
18
35
|
# class Customer < ActiveRecord::Base
|
19
|
-
# composed_of :balance, class_name: "Money", mapping: %w(
|
36
|
+
# composed_of :balance, class_name: "Money", mapping: %w(amount currency)
|
20
37
|
# composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
|
21
38
|
# end
|
22
39
|
#
|
@@ -87,11 +104,6 @@ module ActiveRecord
|
|
87
104
|
# customer.address_city = "Copenhagen"
|
88
105
|
# customer.address # => Address.new("Hyancintvej", "Copenhagen")
|
89
106
|
#
|
90
|
-
# customer.address_street = "Vesterbrogade"
|
91
|
-
# customer.address # => Address.new("Hyancintvej", "Copenhagen")
|
92
|
-
# customer.clear_aggregation_cache
|
93
|
-
# customer.address # => Address.new("Vesterbrogade", "Copenhagen")
|
94
|
-
#
|
95
107
|
# customer.address = Address.new("May Street", "Chicago")
|
96
108
|
# customer.address_street # => "May Street"
|
97
109
|
# customer.address_city # => "Chicago"
|
@@ -108,12 +120,12 @@ module ActiveRecord
|
|
108
120
|
#
|
109
121
|
# It's also important to treat the value objects as immutable. Don't allow the Money object to have
|
110
122
|
# its amount changed after creation. Create a new Money object with the new value instead. The
|
111
|
-
# Money#exchange_to method is an example of this. It returns a new value object instead of changing
|
123
|
+
# <tt>Money#exchange_to</tt> method is an example of this. It returns a new value object instead of changing
|
112
124
|
# its own values. Active Record won't persist value objects that have been changed through means
|
113
125
|
# other than the writer method.
|
114
126
|
#
|
115
127
|
# The immutable requirement is enforced by Active Record by freezing any object assigned as a value
|
116
|
-
# object. Attempting to change it afterwards will result in a RuntimeError
|
128
|
+
# object. Attempting to change it afterwards will result in a +RuntimeError+.
|
117
129
|
#
|
118
130
|
# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
|
119
131
|
# keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
|
@@ -122,17 +134,17 @@ module ActiveRecord
|
|
122
134
|
#
|
123
135
|
# By default value objects are initialized by calling the <tt>new</tt> constructor of the value
|
124
136
|
# class passing each of the mapped attributes, in the order specified by the <tt>:mapping</tt>
|
125
|
-
# option, as arguments. If the value class doesn't support this convention then
|
137
|
+
# option, as arguments. If the value class doesn't support this convention then #composed_of allows
|
126
138
|
# a custom constructor to be specified.
|
127
139
|
#
|
128
140
|
# When a new value is assigned to the value object, the default assumption is that the new value
|
129
141
|
# is an instance of the value class. Specifying a custom converter allows the new value to be automatically
|
130
142
|
# converted to an instance of value class if necessary.
|
131
143
|
#
|
132
|
-
# For example, the NetworkResource model has +network_address+ and +cidr_range+ attributes that should be
|
133
|
-
# aggregated using the NetAddr::CIDR value class (http://www.
|
144
|
+
# For example, the +NetworkResource+ model has +network_address+ and +cidr_range+ attributes that should be
|
145
|
+
# aggregated using the +NetAddr::CIDR+ value class (http://www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR).
|
134
146
|
# The constructor for the value class is called +create+ and it expects a CIDR address string as a parameter.
|
135
|
-
# New values can be assigned to the value object using either another NetAddr::CIDR object, a string
|
147
|
+
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
|
136
148
|
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
137
149
|
# these requirements:
|
138
150
|
#
|
@@ -161,7 +173,7 @@ module ActiveRecord
|
|
161
173
|
#
|
162
174
|
# == Finding records by a value object
|
163
175
|
#
|
164
|
-
# Once a
|
176
|
+
# Once a #composed_of relationship is specified for a model, records can be loaded from the database
|
165
177
|
# by specifying an instance of the value object in the conditions hash. The following example
|
166
178
|
# finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
|
167
179
|
#
|
@@ -174,7 +186,7 @@ module ActiveRecord
|
|
174
186
|
# Options are:
|
175
187
|
# * <tt>:class_name</tt> - Specifies the class name of the association. Use it only if that name
|
176
188
|
# can't be inferred from the part id. So <tt>composed_of :address</tt> will by default be linked
|
177
|
-
# to the Address class, but if the real class name is CompanyAddress
|
189
|
+
# to the Address class, but if the real class name is +CompanyAddress+, you'll have to specify it
|
178
190
|
# with this option.
|
179
191
|
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
180
192
|
# object. Each mapping is represented as an array where the first item is the name of the
|
@@ -252,7 +264,8 @@ module ActiveRecord
|
|
252
264
|
hash_from_multiparameter_assignment = part.is_a?(Hash) &&
|
253
265
|
part.each_key.all? { |k| k.is_a?(Integer) }
|
254
266
|
if hash_from_multiparameter_assignment
|
255
|
-
part
|
267
|
+
raise ArgumentError unless part.size == part.each_key.max
|
268
|
+
part = klass.new(*part.sort.map(&:last))
|
256
269
|
end
|
257
270
|
|
258
271
|
if part.nil? && allow_nil
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class AssociationRelation < Relation
|
3
|
-
def initialize(klass, table, association)
|
4
|
-
super(klass, table)
|
3
|
+
def initialize(klass, table, predicate_builder, association)
|
4
|
+
super(klass, table, predicate_builder)
|
5
5
|
@association = association
|
6
6
|
end
|
7
7
|
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def ==(other)
|
13
|
-
other ==
|
13
|
+
other == records
|
14
14
|
end
|
15
15
|
|
16
16
|
def build(*args, &block)
|
@@ -29,7 +29,10 @@ module ActiveRecord
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def exec_queries
|
32
|
-
super
|
32
|
+
super do |r|
|
33
|
+
@association.set_inverse_instance r
|
34
|
+
yield r if block_given?
|
35
|
+
end
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -5,95 +5,170 @@ require 'active_record/errors'
|
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
7
|
class AssociationNotFoundError < ConfigurationError #:nodoc:
|
8
|
-
def initialize(record, association_name)
|
9
|
-
|
8
|
+
def initialize(record = nil, association_name = nil)
|
9
|
+
if record && association_name
|
10
|
+
super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
|
11
|
+
else
|
12
|
+
super("Association was not found.")
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
13
17
|
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
|
14
|
-
def initialize(reflection, associated_class = nil)
|
15
|
-
|
18
|
+
def initialize(reflection = nil, associated_class = nil)
|
19
|
+
if reflection
|
20
|
+
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
|
21
|
+
else
|
22
|
+
super("Could not find the inverse association.")
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
18
26
|
|
19
27
|
class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
|
20
|
-
def initialize(owner_class_name, reflection)
|
21
|
-
|
28
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
29
|
+
if owner_class_name && reflection
|
30
|
+
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
|
31
|
+
else
|
32
|
+
super("Could not find the association.")
|
33
|
+
end
|
22
34
|
end
|
23
35
|
end
|
24
36
|
|
25
37
|
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc:
|
26
|
-
def initialize(owner_class_name, reflection, source_reflection)
|
27
|
-
|
38
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
39
|
+
if owner_class_name && reflection && source_reflection
|
40
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
|
41
|
+
else
|
42
|
+
super("Cannot have a has_many :through association.")
|
43
|
+
end
|
28
44
|
end
|
29
45
|
end
|
30
46
|
|
31
47
|
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
|
32
|
-
def initialize(owner_class_name, reflection)
|
33
|
-
|
48
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
49
|
+
if owner_class_name && reflection
|
50
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
51
|
+
else
|
52
|
+
super("Cannot have a has_many :through association.")
|
53
|
+
end
|
34
54
|
end
|
35
55
|
end
|
36
56
|
|
37
57
|
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
|
38
|
-
def initialize(owner_class_name, reflection, source_reflection)
|
39
|
-
|
58
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
59
|
+
if owner_class_name && reflection && source_reflection
|
60
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
|
61
|
+
else
|
62
|
+
super("Cannot have a has_many :through association.")
|
63
|
+
end
|
40
64
|
end
|
41
65
|
end
|
42
66
|
|
43
67
|
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc:
|
44
|
-
def initialize(owner_class_name, reflection, through_reflection)
|
45
|
-
|
68
|
+
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
69
|
+
if owner_class_name && reflection && through_reflection
|
70
|
+
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
|
71
|
+
else
|
72
|
+
super("Cannot have a has_one :through association.")
|
73
|
+
end
|
46
74
|
end
|
47
75
|
end
|
48
76
|
|
49
77
|
class HasOneAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
|
50
|
-
def initialize(owner_class_name, reflection)
|
51
|
-
|
78
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
79
|
+
if owner_class_name && reflection
|
80
|
+
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
81
|
+
else
|
82
|
+
super("Cannot have a has_one :through association.")
|
83
|
+
end
|
52
84
|
end
|
53
85
|
end
|
54
86
|
|
55
87
|
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
|
56
|
-
def initialize(reflection)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
88
|
+
def initialize(reflection = nil)
|
89
|
+
if reflection
|
90
|
+
through_reflection = reflection.through_reflection
|
91
|
+
source_reflection_names = reflection.source_reflection_names
|
92
|
+
source_associations = reflection.through_reflection.klass._reflections.keys
|
93
|
+
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)}?")
|
94
|
+
else
|
95
|
+
super("Could not find the source association(s).")
|
96
|
+
end
|
61
97
|
end
|
62
98
|
end
|
63
99
|
|
64
|
-
class
|
65
|
-
def initialize(owner, reflection)
|
66
|
-
|
100
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
|
101
|
+
def initialize(owner = nil, reflection = nil)
|
102
|
+
if owner && reflection
|
103
|
+
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
|
104
|
+
else
|
105
|
+
super("Cannot modify association.")
|
106
|
+
end
|
67
107
|
end
|
68
108
|
end
|
69
109
|
|
110
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
|
111
|
+
end
|
112
|
+
|
113
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
|
114
|
+
end
|
115
|
+
|
70
116
|
class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
|
71
|
-
def initialize(owner, reflection)
|
72
|
-
|
117
|
+
def initialize(owner = nil, reflection = nil)
|
118
|
+
if owner && reflection
|
119
|
+
super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
|
120
|
+
else
|
121
|
+
super("Cannot associate new records.")
|
122
|
+
end
|
73
123
|
end
|
74
124
|
end
|
75
125
|
|
76
126
|
class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
|
77
|
-
def initialize(owner, reflection)
|
78
|
-
|
127
|
+
def initialize(owner = nil, reflection = nil)
|
128
|
+
if owner && reflection
|
129
|
+
super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
|
130
|
+
else
|
131
|
+
super("Cannot dissociate new records.")
|
132
|
+
end
|
79
133
|
end
|
80
134
|
end
|
81
135
|
|
82
|
-
class
|
83
|
-
def initialize(owner, reflection)
|
84
|
-
|
136
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
|
137
|
+
def initialize(owner = nil, reflection = nil)
|
138
|
+
if owner && reflection
|
139
|
+
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
140
|
+
else
|
141
|
+
super("Through nested associations are read-only.")
|
142
|
+
end
|
85
143
|
end
|
86
144
|
end
|
87
145
|
|
88
|
-
class
|
89
|
-
|
90
|
-
|
146
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
|
147
|
+
end
|
148
|
+
|
149
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
|
150
|
+
end
|
151
|
+
|
152
|
+
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
153
|
+
# Eager loading polymorphic associations is only possible with
|
154
|
+
# {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
|
155
|
+
class EagerLoadPolymorphicError < ActiveRecordError
|
156
|
+
def initialize(reflection = nil)
|
157
|
+
if reflection
|
158
|
+
super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
|
159
|
+
else
|
160
|
+
super("Eager load polymorphic error.")
|
161
|
+
end
|
91
162
|
end
|
92
163
|
end
|
93
164
|
|
94
165
|
class ReadOnlyAssociation < ActiveRecordError #:nodoc:
|
95
|
-
def initialize(reflection)
|
96
|
-
|
166
|
+
def initialize(reflection = nil)
|
167
|
+
if reflection
|
168
|
+
super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
|
169
|
+
else
|
170
|
+
super("Read-only reflection error.")
|
171
|
+
end
|
97
172
|
end
|
98
173
|
end
|
99
174
|
|
@@ -101,8 +176,12 @@ module ActiveRecord
|
|
101
176
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
102
177
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
103
178
|
class DeleteRestrictionError < ActiveRecordError #:nodoc:
|
104
|
-
def initialize(name)
|
105
|
-
|
179
|
+
def initialize(name = nil)
|
180
|
+
if name
|
181
|
+
super("Cannot delete record because of dependent #{name}")
|
182
|
+
else
|
183
|
+
super("Delete restriction error.")
|
184
|
+
end
|
106
185
|
end
|
107
186
|
end
|
108
187
|
|
@@ -113,19 +192,12 @@ module ActiveRecord
|
|
113
192
|
|
114
193
|
# These classes will be loaded when associations are created.
|
115
194
|
# So there is no need to eager load them.
|
116
|
-
autoload :Association
|
117
|
-
autoload :SingularAssociation
|
118
|
-
autoload :CollectionAssociation
|
119
|
-
autoload :ForeignAssociation
|
120
|
-
autoload :CollectionProxy
|
121
|
-
|
122
|
-
autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
|
123
|
-
autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
|
124
|
-
autoload :HasManyAssociation, 'active_record/associations/has_many_association'
|
125
|
-
autoload :HasManyThroughAssociation, 'active_record/associations/has_many_through_association'
|
126
|
-
autoload :HasOneAssociation, 'active_record/associations/has_one_association'
|
127
|
-
autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
|
128
|
-
autoload :ThroughAssociation, 'active_record/associations/through_association'
|
195
|
+
autoload :Association
|
196
|
+
autoload :SingularAssociation
|
197
|
+
autoload :CollectionAssociation
|
198
|
+
autoload :ForeignAssociation
|
199
|
+
autoload :CollectionProxy
|
200
|
+
autoload :ThroughAssociation
|
129
201
|
|
130
202
|
module Builder #:nodoc:
|
131
203
|
autoload :Association, 'active_record/associations/builder/association'
|
@@ -139,26 +211,32 @@ module ActiveRecord
|
|
139
211
|
end
|
140
212
|
|
141
213
|
eager_autoload do
|
142
|
-
autoload :
|
143
|
-
autoload :
|
144
|
-
autoload :
|
145
|
-
autoload :
|
146
|
-
|
214
|
+
autoload :BelongsToAssociation
|
215
|
+
autoload :BelongsToPolymorphicAssociation
|
216
|
+
autoload :HasManyAssociation
|
217
|
+
autoload :HasManyThroughAssociation
|
218
|
+
autoload :HasOneAssociation
|
219
|
+
autoload :HasOneThroughAssociation
|
147
220
|
|
148
|
-
|
149
|
-
|
150
|
-
|
221
|
+
autoload :Preloader
|
222
|
+
autoload :JoinDependency
|
223
|
+
autoload :AssociationScope
|
224
|
+
autoload :AliasTracker
|
151
225
|
end
|
152
226
|
|
153
|
-
|
154
|
-
|
227
|
+
def self.eager_load!
|
228
|
+
super
|
229
|
+
Preloader.eager_load!
|
230
|
+
end
|
155
231
|
|
156
232
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
157
233
|
def association(name) #:nodoc:
|
158
234
|
association = association_instance_get(name)
|
159
235
|
|
160
236
|
if association.nil?
|
161
|
-
|
237
|
+
unless reflection = self.class._reflect_on_association(name)
|
238
|
+
raise AssociationNotFoundError.new(self, name)
|
239
|
+
end
|
162
240
|
association = reflection.association_class.new(self, reflection)
|
163
241
|
association_instance_set(name, association)
|
164
242
|
end
|
@@ -166,8 +244,32 @@ module ActiveRecord
|
|
166
244
|
association
|
167
245
|
end
|
168
246
|
|
247
|
+
def association_cached?(name) # :nodoc
|
248
|
+
@association_cache.key?(name)
|
249
|
+
end
|
250
|
+
|
251
|
+
def initialize_dup(*) # :nodoc:
|
252
|
+
@association_cache = {}
|
253
|
+
super
|
254
|
+
end
|
255
|
+
|
256
|
+
def reload(*) # :nodoc:
|
257
|
+
clear_association_cache
|
258
|
+
super
|
259
|
+
end
|
260
|
+
|
169
261
|
private
|
170
|
-
#
|
262
|
+
# Clears out the association cache.
|
263
|
+
def clear_association_cache # :nodoc:
|
264
|
+
@association_cache.clear if persisted?
|
265
|
+
end
|
266
|
+
|
267
|
+
def init_internals # :nodoc:
|
268
|
+
@association_cache = {}
|
269
|
+
super
|
270
|
+
end
|
271
|
+
|
272
|
+
# Returns the specified association instance if it exists, nil otherwise.
|
171
273
|
def association_instance_get(name)
|
172
274
|
@association_cache[name]
|
173
275
|
end
|
@@ -204,7 +306,7 @@ module ActiveRecord
|
|
204
306
|
# === A word of warning
|
205
307
|
#
|
206
308
|
# Don't create associations that have the same name as instance methods of
|
207
|
-
#
|
309
|
+
# ActiveRecord::Base. Since the association adds a method with that name to
|
208
310
|
# its model, it will override the inherited method and break things.
|
209
311
|
# For instance, +attributes+ and +connection+ would be bad choices for association names.
|
210
312
|
#
|
@@ -215,17 +317,18 @@ module ActiveRecord
|
|
215
317
|
# | | belongs_to |
|
216
318
|
# generated methods | belongs_to | :polymorphic | has_one
|
217
319
|
# ----------------------------------+------------+--------------+---------
|
218
|
-
# other
|
320
|
+
# other | X | X | X
|
219
321
|
# other=(other) | X | X | X
|
220
322
|
# build_other(attributes={}) | X | | X
|
221
323
|
# create_other(attributes={}) | X | | X
|
222
324
|
# create_other!(attributes={}) | X | | X
|
325
|
+
# reload_other | X | X | X
|
223
326
|
#
|
224
|
-
# ===Collection associations (one-to-many / many-to-many)
|
327
|
+
# === Collection associations (one-to-many / many-to-many)
|
225
328
|
# | | | has_many
|
226
329
|
# generated methods | habtm | has_many | :through
|
227
330
|
# ----------------------------------+-------+----------+----------
|
228
|
-
# others
|
331
|
+
# others | X | X | X
|
229
332
|
# others=(other,other,...) | X | X | X
|
230
333
|
# other_ids | X | X | X
|
231
334
|
# other_ids=(id,id,...) | X | X | X
|
@@ -248,8 +351,8 @@ module ActiveRecord
|
|
248
351
|
# others.find(*args) | X | X | X
|
249
352
|
# others.exists? | X | X | X
|
250
353
|
# others.distinct | X | X | X
|
251
|
-
# others.uniq | X | X | X
|
252
354
|
# others.reset | X | X | X
|
355
|
+
# others.reload | X | X | X
|
253
356
|
#
|
254
357
|
# === Overriding generated methods
|
255
358
|
#
|
@@ -267,7 +370,7 @@ module ActiveRecord
|
|
267
370
|
# end
|
268
371
|
#
|
269
372
|
# If your model class is <tt>Project</tt>, the module is
|
270
|
-
# named <tt>Project::
|
373
|
+
# named <tt>Project::GeneratedAssociationMethods</tt>. The +GeneratedAssociationMethods+ module is
|
271
374
|
# included in the model class immediately after the (anonymous) generated attributes methods
|
272
375
|
# module, meaning an association will override the methods for an attribute with the same name.
|
273
376
|
#
|
@@ -275,12 +378,12 @@ module ActiveRecord
|
|
275
378
|
#
|
276
379
|
# Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
|
277
380
|
# relationships between models. Each model uses an association to describe its role in
|
278
|
-
# the relation. The
|
381
|
+
# the relation. The #belongs_to association is always used in the model that has
|
279
382
|
# the foreign key.
|
280
383
|
#
|
281
384
|
# === One-to-one
|
282
385
|
#
|
283
|
-
# Use
|
386
|
+
# Use #has_one in the base, and #belongs_to in the associated model.
|
284
387
|
#
|
285
388
|
# class Employee < ActiveRecord::Base
|
286
389
|
# has_one :office
|
@@ -291,7 +394,7 @@ module ActiveRecord
|
|
291
394
|
#
|
292
395
|
# === One-to-many
|
293
396
|
#
|
294
|
-
# Use
|
397
|
+
# Use #has_many in the base, and #belongs_to in the associated model.
|
295
398
|
#
|
296
399
|
# class Manager < ActiveRecord::Base
|
297
400
|
# has_many :employees
|
@@ -304,7 +407,7 @@ module ActiveRecord
|
|
304
407
|
#
|
305
408
|
# There are two ways to build a many-to-many relationship.
|
306
409
|
#
|
307
|
-
# The first way uses a
|
410
|
+
# The first way uses a #has_many association with the <tt>:through</tt> option and a join model, so
|
308
411
|
# there are two stages of associations.
|
309
412
|
#
|
310
413
|
# class Assignment < ActiveRecord::Base
|
@@ -320,7 +423,7 @@ module ActiveRecord
|
|
320
423
|
# has_many :programmers, through: :assignments
|
321
424
|
# end
|
322
425
|
#
|
323
|
-
# For the second way, use
|
426
|
+
# For the second way, use #has_and_belongs_to_many in both models. This requires a join table
|
324
427
|
# that has no corresponding model or primary key.
|
325
428
|
#
|
326
429
|
# class Programmer < ActiveRecord::Base
|
@@ -332,13 +435,13 @@ module ActiveRecord
|
|
332
435
|
#
|
333
436
|
# Choosing which way to build a many-to-many relationship is not always simple.
|
334
437
|
# If you need to work with the relationship model as its own entity,
|
335
|
-
# use <tt
|
438
|
+
# use #has_many <tt>:through</tt>. Use #has_and_belongs_to_many when working with legacy schemas or when
|
336
439
|
# you never work directly with the relationship itself.
|
337
440
|
#
|
338
|
-
# == Is it a
|
441
|
+
# == Is it a #belongs_to or #has_one association?
|
339
442
|
#
|
340
443
|
# Both express a 1-1 relationship. The difference is mostly where to place the foreign
|
341
|
-
# key, which goes on the table for the class declaring the
|
444
|
+
# key, which goes on the table for the class declaring the #belongs_to relationship.
|
342
445
|
#
|
343
446
|
# class User < ActiveRecord::Base
|
344
447
|
# # I reference an account.
|
@@ -353,14 +456,14 @@ module ActiveRecord
|
|
353
456
|
# The tables for these classes could look something like:
|
354
457
|
#
|
355
458
|
# CREATE TABLE users (
|
356
|
-
# id int
|
357
|
-
# account_id int
|
459
|
+
# id int NOT NULL auto_increment,
|
460
|
+
# account_id int default NULL,
|
358
461
|
# name varchar default NULL,
|
359
462
|
# PRIMARY KEY (id)
|
360
463
|
# )
|
361
464
|
#
|
362
465
|
# CREATE TABLE accounts (
|
363
|
-
# id int
|
466
|
+
# id int NOT NULL auto_increment,
|
364
467
|
# name varchar default NULL,
|
365
468
|
# PRIMARY KEY (id)
|
366
469
|
# )
|
@@ -371,35 +474,35 @@ module ActiveRecord
|
|
371
474
|
# there is some special behavior you should be aware of, mostly involving the saving of
|
372
475
|
# associated objects.
|
373
476
|
#
|
374
|
-
# You can set the <tt>:autosave</tt> option on a
|
375
|
-
#
|
477
|
+
# You can set the <tt>:autosave</tt> option on a #has_one, #belongs_to,
|
478
|
+
# #has_many, or #has_and_belongs_to_many association. Setting it
|
376
479
|
# to +true+ will _always_ save the members, whereas setting it to +false+ will
|
377
480
|
# _never_ save the members. More details about <tt>:autosave</tt> option is available at
|
378
481
|
# AutosaveAssociation.
|
379
482
|
#
|
380
483
|
# === One-to-one associations
|
381
484
|
#
|
382
|
-
# * Assigning an object to a
|
485
|
+
# * Assigning an object to a #has_one association automatically saves that object and
|
383
486
|
# the object being replaced (if there is one), in order to update their foreign
|
384
487
|
# keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
|
385
488
|
# * If either of these saves fail (due to one of the objects being invalid), an
|
386
|
-
#
|
489
|
+
# ActiveRecord::RecordNotSaved exception is raised and the assignment is
|
387
490
|
# cancelled.
|
388
|
-
# * If you wish to assign an object to a
|
389
|
-
# use the <tt
|
491
|
+
# * If you wish to assign an object to a #has_one association without saving it,
|
492
|
+
# use the <tt>#build_association</tt> method (documented below). The object being
|
390
493
|
# replaced will still be saved to update its foreign key.
|
391
|
-
# * Assigning an object to a
|
494
|
+
# * Assigning an object to a #belongs_to association does not save the object, since
|
392
495
|
# the foreign key field belongs on the parent. It does not save the parent either.
|
393
496
|
#
|
394
497
|
# === Collections
|
395
498
|
#
|
396
|
-
# * Adding an object to a collection (
|
499
|
+
# * Adding an object to a collection (#has_many or #has_and_belongs_to_many) automatically
|
397
500
|
# saves that object, except if the parent object (the owner of the collection) is not yet
|
398
501
|
# stored in the database.
|
399
502
|
# * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
|
400
503
|
# fails, then <tt>push</tt> returns +false+.
|
401
504
|
# * If saving fails while replacing the collection (via <tt>association=</tt>), an
|
402
|
-
#
|
505
|
+
# ActiveRecord::RecordNotSaved exception is raised and the assignment is
|
403
506
|
# cancelled.
|
404
507
|
# * You can add an object to a collection without automatically saving it by using the
|
405
508
|
# <tt>collection.build</tt> method (documented below).
|
@@ -408,14 +511,14 @@ module ActiveRecord
|
|
408
511
|
#
|
409
512
|
# == Customizing the query
|
410
513
|
#
|
411
|
-
# \Associations are built from <tt>Relation</tt>
|
514
|
+
# \Associations are built from <tt>Relation</tt> objects, and you can use the Relation syntax
|
412
515
|
# to customize them. For example, to add a condition:
|
413
516
|
#
|
414
517
|
# class Blog < ActiveRecord::Base
|
415
|
-
# has_many :published_posts, -> { where
|
518
|
+
# has_many :published_posts, -> { where(published: true) }, class_name: 'Post'
|
416
519
|
# end
|
417
520
|
#
|
418
|
-
# Inside the <tt>-> { ... }</tt> block you can use all of the usual
|
521
|
+
# Inside the <tt>-> { ... }</tt> block you can use all of the usual Relation methods.
|
419
522
|
#
|
420
523
|
# === Accessing the owner object
|
421
524
|
#
|
@@ -424,7 +527,7 @@ module ActiveRecord
|
|
424
527
|
# events that occur on the user's birthday:
|
425
528
|
#
|
426
529
|
# class User < ActiveRecord::Base
|
427
|
-
# has_many :birthday_events, ->(user) { where
|
530
|
+
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
428
531
|
# end
|
429
532
|
#
|
430
533
|
# Note: Joining, eager loading and preloading of these associations is not fully possible.
|
@@ -503,8 +606,8 @@ module ActiveRecord
|
|
503
606
|
#
|
504
607
|
# * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
|
505
608
|
# * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
|
506
|
-
# * <tt>record.association(:items).target</tt> - Returns the associated object for
|
507
|
-
# the collection of associated objects for
|
609
|
+
# * <tt>record.association(:items).target</tt> - Returns the associated object for #belongs_to and #has_one, or
|
610
|
+
# the collection of associated objects for #has_many and #has_and_belongs_to_many.
|
508
611
|
#
|
509
612
|
# However, inside the actual extension code, you will not have access to the <tt>record</tt> as
|
510
613
|
# above. In this case, you can access <tt>proxy_association</tt>. For example,
|
@@ -516,7 +619,7 @@ module ActiveRecord
|
|
516
619
|
#
|
517
620
|
# Has Many associations can be configured with the <tt>:through</tt> option to use an
|
518
621
|
# explicit join model to retrieve the data. This operates similarly to a
|
519
|
-
#
|
622
|
+
# #has_and_belongs_to_many association. The advantage is that you're able to add validations,
|
520
623
|
# callbacks, and extra attributes on the join model. Consider the following schema:
|
521
624
|
#
|
522
625
|
# class Author < ActiveRecord::Base
|
@@ -533,7 +636,7 @@ module ActiveRecord
|
|
533
636
|
# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
|
534
637
|
# @author.books # selects all books by using the Authorship join model
|
535
638
|
#
|
536
|
-
# You can also go through a
|
639
|
+
# You can also go through a #has_many association on the join model:
|
537
640
|
#
|
538
641
|
# class Firm < ActiveRecord::Base
|
539
642
|
# has_many :clients
|
@@ -553,7 +656,7 @@ module ActiveRecord
|
|
553
656
|
# @firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm
|
554
657
|
# @firm.invoices # selects all invoices by going through the Client join model
|
555
658
|
#
|
556
|
-
# Similarly you can go through a
|
659
|
+
# Similarly you can go through a #has_one association on the join model:
|
557
660
|
#
|
558
661
|
# class Group < ActiveRecord::Base
|
559
662
|
# has_many :users
|
@@ -573,7 +676,7 @@ module ActiveRecord
|
|
573
676
|
# @group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
|
574
677
|
# @group.avatars # selects all avatars by going through the User join model.
|
575
678
|
#
|
576
|
-
# An important caveat with going through
|
679
|
+
# An important caveat with going through #has_one or #has_many associations on the
|
577
680
|
# join model is that these associations are *read-only*. For example, the following
|
578
681
|
# would not work following the previous example:
|
579
682
|
#
|
@@ -582,26 +685,26 @@ module ActiveRecord
|
|
582
685
|
#
|
583
686
|
# == Setting Inverses
|
584
687
|
#
|
585
|
-
# If you are using a
|
586
|
-
# <tt>:inverse_of</tt> option on the
|
587
|
-
# works correctly (where <tt>tags</tt> is a
|
688
|
+
# If you are using a #belongs_to on the join model, it is a good idea to set the
|
689
|
+
# <tt>:inverse_of</tt> option on the #belongs_to, which will mean that the following example
|
690
|
+
# works correctly (where <tt>tags</tt> is a #has_many <tt>:through</tt> association):
|
588
691
|
#
|
589
692
|
# @post = Post.first
|
590
693
|
# @tag = @post.tags.build name: "ruby"
|
591
694
|
# @tag.save
|
592
695
|
#
|
593
|
-
# The last line ought to save the through record (a <tt>
|
696
|
+
# The last line ought to save the through record (a <tt>Tagging</tt>). This will only work if the
|
594
697
|
# <tt>:inverse_of</tt> is set:
|
595
698
|
#
|
596
|
-
# class
|
699
|
+
# class Tagging < ActiveRecord::Base
|
597
700
|
# belongs_to :post
|
598
701
|
# belongs_to :tag, inverse_of: :taggings
|
599
702
|
# end
|
600
703
|
#
|
601
704
|
# If you do not set the <tt>:inverse_of</tt> record, the association will
|
602
705
|
# do its best to match itself up with the correct inverse. Automatic
|
603
|
-
# inverse detection only works on
|
604
|
-
#
|
706
|
+
# inverse detection only works on #has_many, #has_one, and
|
707
|
+
# #belongs_to associations.
|
605
708
|
#
|
606
709
|
# Extra options on the associations, as defined in the
|
607
710
|
# <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> constant, will
|
@@ -614,7 +717,7 @@ module ActiveRecord
|
|
614
717
|
# You can turn off the automatic detection of inverse associations by setting
|
615
718
|
# the <tt>:inverse_of</tt> option to <tt>false</tt> like so:
|
616
719
|
#
|
617
|
-
# class
|
720
|
+
# class Tagging < ActiveRecord::Base
|
618
721
|
# belongs_to :tag, inverse_of: false
|
619
722
|
# end
|
620
723
|
#
|
@@ -664,7 +767,7 @@ module ActiveRecord
|
|
664
767
|
# == Polymorphic \Associations
|
665
768
|
#
|
666
769
|
# Polymorphic associations on models are not restricted on what types of models they
|
667
|
-
# can be associated with. Rather, they specify an interface that a
|
770
|
+
# can be associated with. Rather, they specify an interface that a #has_many association
|
668
771
|
# must adhere to.
|
669
772
|
#
|
670
773
|
# class Asset < ActiveRecord::Base
|
@@ -748,7 +851,7 @@ module ActiveRecord
|
|
748
851
|
#
|
749
852
|
# Post.includes(:author).each do |post|
|
750
853
|
#
|
751
|
-
# This references the name of the
|
854
|
+
# This references the name of the #belongs_to association that also used the <tt>:author</tt>
|
752
855
|
# symbol. After loading the posts, find will collect the +author_id+ from each one and load
|
753
856
|
# all the referenced authors with one query. Doing so will cut down the number of queries
|
754
857
|
# from 201 to 102.
|
@@ -759,7 +862,7 @@ module ActiveRecord
|
|
759
862
|
#
|
760
863
|
# This will load all comments with a single query. This reduces the total number of queries
|
761
864
|
# to 3. In general, the number of queries will be 1 plus the number of associations
|
762
|
-
# named (except if some of the associations are polymorphic
|
865
|
+
# named (except if some of the associations are polymorphic #belongs_to - see below).
|
763
866
|
#
|
764
867
|
# To include a deep hierarchy of associations, use a hash:
|
765
868
|
#
|
@@ -799,7 +902,7 @@ module ActiveRecord
|
|
799
902
|
# In this case it is usually more natural to include an association which has conditions defined on it:
|
800
903
|
#
|
801
904
|
# class Post < ActiveRecord::Base
|
802
|
-
# has_many :approved_comments, -> { where
|
905
|
+
# has_many :approved_comments, -> { where(approved: true) }, class_name: 'Comment'
|
803
906
|
# end
|
804
907
|
#
|
805
908
|
# Post.includes(:approved_comments)
|
@@ -831,7 +934,7 @@ module ActiveRecord
|
|
831
934
|
# For example if all the addressables are either of class Person or Company then a total
|
832
935
|
# of 3 queries will be executed. The list of addressable types to load is determined on
|
833
936
|
# the back of the addresses loaded. This is not supported if Active Record has to fallback
|
834
|
-
# to the previous implementation of eager loading and will raise
|
937
|
+
# to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
|
835
938
|
# The reason is that the parent model's type is a column value so its corresponding table
|
836
939
|
# name cannot be put in the +FROM+/+JOIN+ clauses of that query.
|
837
940
|
#
|
@@ -873,7 +976,7 @@ module ActiveRecord
|
|
873
976
|
# INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
874
977
|
# INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
875
978
|
#
|
876
|
-
# If you wish to specify your own custom joins using
|
979
|
+
# If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
|
877
980
|
# names will take precedence over the eager associations:
|
878
981
|
#
|
879
982
|
# Post.joins(:comments).joins("inner join comments ...")
|
@@ -938,20 +1041,16 @@ module ActiveRecord
|
|
938
1041
|
# The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
|
939
1042
|
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
|
940
1043
|
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
|
941
|
-
# Active Record
|
942
|
-
#
|
1044
|
+
# Active Record can guess the inverse of the association based on the name
|
1045
|
+
# of the class. The result is the following:
|
943
1046
|
#
|
944
1047
|
# d = Dungeon.first
|
945
1048
|
# t = d.traps.first
|
946
|
-
# d.
|
947
|
-
# d.level = 10
|
948
|
-
# d.level == t.dungeon.level # => false
|
1049
|
+
# d.object_id == t.dungeon.object_id # => true
|
949
1050
|
#
|
950
1051
|
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
|
951
|
-
# the same
|
952
|
-
#
|
953
|
-
# Active Record about inverse relationships and it will optimise object loading. For
|
954
|
-
# example, if we changed our model definitions to:
|
1052
|
+
# the same in-memory instance since the association matches the name of the class.
|
1053
|
+
# The result would be the same if we added +:inverse_of+ to our model definitions:
|
955
1054
|
#
|
956
1055
|
# class Dungeon < ActiveRecord::Base
|
957
1056
|
# has_many :traps, inverse_of: :dungeon
|
@@ -966,20 +1065,19 @@ module ActiveRecord
|
|
966
1065
|
# belongs_to :dungeon, inverse_of: :evil_wizard
|
967
1066
|
# end
|
968
1067
|
#
|
969
|
-
# Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
|
970
|
-
# in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
|
971
|
-
#
|
972
1068
|
# There are limitations to <tt>:inverse_of</tt> support:
|
973
1069
|
#
|
974
1070
|
# * does not work with <tt>:through</tt> associations.
|
975
1071
|
# * does not work with <tt>:polymorphic</tt> associations.
|
976
|
-
# * for
|
1072
|
+
# * for #belongs_to associations #has_many inverse associations are ignored.
|
1073
|
+
#
|
1074
|
+
# For more information, see the documentation for the +:inverse_of+ option.
|
977
1075
|
#
|
978
1076
|
# == Deleting from associations
|
979
1077
|
#
|
980
1078
|
# === Dependent associations
|
981
1079
|
#
|
982
|
-
#
|
1080
|
+
# #has_many, #has_one and #belongs_to associations support the <tt>:dependent</tt> option.
|
983
1081
|
# This allows you to specify that associated records should be deleted when the owner is
|
984
1082
|
# deleted.
|
985
1083
|
#
|
@@ -1000,20 +1098,22 @@ module ActiveRecord
|
|
1000
1098
|
# callbacks declared either before or after the <tt>:dependent</tt> option
|
1001
1099
|
# can affect what it does.
|
1002
1100
|
#
|
1101
|
+
# Note that <tt>:dependent</tt> option is ignored for #has_one <tt>:through</tt> associations.
|
1102
|
+
#
|
1003
1103
|
# === Delete or destroy?
|
1004
1104
|
#
|
1005
|
-
#
|
1105
|
+
# #has_many and #has_and_belongs_to_many associations have the methods <tt>destroy</tt>,
|
1006
1106
|
# <tt>delete</tt>, <tt>destroy_all</tt> and <tt>delete_all</tt>.
|
1007
1107
|
#
|
1008
|
-
# For
|
1108
|
+
# For #has_and_belongs_to_many, <tt>delete</tt> and <tt>destroy</tt> are the same: they
|
1009
1109
|
# cause the records in the join table to be removed.
|
1010
1110
|
#
|
1011
|
-
# For
|
1111
|
+
# For #has_many, <tt>destroy</tt> and <tt>destroy_all</tt> will always call the <tt>destroy</tt> method of the
|
1012
1112
|
# record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either
|
1013
1113
|
# do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
|
1014
1114
|
# if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
|
1015
1115
|
# The default strategy is to do nothing (leave the foreign keys with the parent ids set), except for
|
1016
|
-
#
|
1116
|
+
# #has_many <tt>:through</tt>, where the default strategy is <tt>delete_all</tt> (delete
|
1017
1117
|
# the join records, without running their callbacks).
|
1018
1118
|
#
|
1019
1119
|
# There is also a <tt>clear</tt> method which is the same as <tt>delete_all</tt>, except that
|
@@ -1021,13 +1121,13 @@ module ActiveRecord
|
|
1021
1121
|
#
|
1022
1122
|
# === What gets deleted?
|
1023
1123
|
#
|
1024
|
-
# There is a potential pitfall here:
|
1124
|
+
# There is a potential pitfall here: #has_and_belongs_to_many and #has_many <tt>:through</tt>
|
1025
1125
|
# associations have records in join tables, as well as the associated records. So when we
|
1026
1126
|
# call one of these deletion methods, what exactly should be deleted?
|
1027
1127
|
#
|
1028
1128
|
# The answer is that it is assumed that deletion on an association is about removing the
|
1029
1129
|
# <i>link</i> between the owner and the associated object(s), rather than necessarily the
|
1030
|
-
# associated objects themselves. So with
|
1130
|
+
# associated objects themselves. So with #has_and_belongs_to_many and #has_many
|
1031
1131
|
# <tt>:through</tt>, the join records will be deleted, but the associated records won't.
|
1032
1132
|
#
|
1033
1133
|
# This makes sense if you think about it: if you were to call <tt>post.tags.delete(Tag.find_by(name: 'food'))</tt>
|
@@ -1038,20 +1138,20 @@ module ActiveRecord
|
|
1038
1138
|
# a person has many projects, and each project has many tasks. If we deleted one of a person's
|
1039
1139
|
# tasks, we would probably not want the project to be deleted. In this scenario, the delete method
|
1040
1140
|
# won't actually work: it can only be used if the association on the join model is a
|
1041
|
-
#
|
1141
|
+
# #belongs_to. In other situations you are expected to perform operations directly on
|
1042
1142
|
# either the associated records or the <tt>:through</tt> association.
|
1043
1143
|
#
|
1044
|
-
# With a regular
|
1144
|
+
# With a regular #has_many there is no distinction between the "associated records"
|
1045
1145
|
# and the "link", so there is only one choice for what gets deleted.
|
1046
1146
|
#
|
1047
|
-
# With
|
1147
|
+
# With #has_and_belongs_to_many and #has_many <tt>:through</tt>, if you want to delete the
|
1048
1148
|
# associated records themselves, you can always do something along the lines of
|
1049
1149
|
# <tt>person.tasks.each(&:destroy)</tt>.
|
1050
1150
|
#
|
1051
|
-
# == Type safety with
|
1151
|
+
# == Type safety with ActiveRecord::AssociationTypeMismatch
|
1052
1152
|
#
|
1053
1153
|
# If you attempt to assign an object to an association that doesn't match the inferred
|
1054
|
-
# or specified <tt>:class_name</tt>, you'll get an
|
1154
|
+
# or specified <tt>:class_name</tt>, you'll get an ActiveRecord::AssociationTypeMismatch.
|
1055
1155
|
#
|
1056
1156
|
# == Options
|
1057
1157
|
#
|
@@ -1064,13 +1164,14 @@ module ActiveRecord
|
|
1064
1164
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
1065
1165
|
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
|
1066
1166
|
#
|
1067
|
-
# [collection
|
1068
|
-
# Returns
|
1069
|
-
# An empty
|
1167
|
+
# [collection]
|
1168
|
+
# Returns a Relation of all the associated objects.
|
1169
|
+
# An empty Relation is returned if none are found.
|
1070
1170
|
# [collection<<(object, ...)]
|
1071
1171
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
1072
1172
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
1073
1173
|
# parent object, unless the parent object is a new record.
|
1174
|
+
# This will also run validations and callbacks of associated object(s).
|
1074
1175
|
# [collection.delete(object, ...)]
|
1075
1176
|
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
|
1076
1177
|
# Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
|
@@ -1088,7 +1189,8 @@ module ActiveRecord
|
|
1088
1189
|
# [collection=objects]
|
1089
1190
|
# Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
|
1090
1191
|
# option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
|
1091
|
-
# direct.
|
1192
|
+
# direct by default. You can specify <tt>dependent: :destroy</tt> or
|
1193
|
+
# <tt>dependent: :nullify</tt> to override this.
|
1092
1194
|
# [collection_singular_ids]
|
1093
1195
|
# Returns an array of the associated objects' ids
|
1094
1196
|
# [collection_singular_ids=ids]
|
@@ -1105,10 +1207,10 @@ module ActiveRecord
|
|
1105
1207
|
# [collection.size]
|
1106
1208
|
# Returns the number of associated objects.
|
1107
1209
|
# [collection.find(...)]
|
1108
|
-
# Finds an associated object according to the same rules as
|
1210
|
+
# Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
|
1109
1211
|
# [collection.exists?(...)]
|
1110
1212
|
# Checks whether an associated object with the given conditions exists.
|
1111
|
-
# Uses the same rules as
|
1213
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1112
1214
|
# [collection.build(attributes = {}, ...)]
|
1113
1215
|
# Returns one or more new objects of the collection type that have been instantiated
|
1114
1216
|
# with +attributes+ and linked to this object through a foreign key, but have not yet
|
@@ -1119,8 +1221,11 @@ module ActiveRecord
|
|
1119
1221
|
# been saved (if it passed the validation). *Note*: This only works if the base model
|
1120
1222
|
# already exists in the DB, not if it is a new (unsaved) record!
|
1121
1223
|
# [collection.create!(attributes = {})]
|
1122
|
-
# Does the same as <tt>collection.create</tt>, but raises
|
1224
|
+
# Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
|
1123
1225
|
# if the record is invalid.
|
1226
|
+
# [collection.reload]
|
1227
|
+
# Returns a Relation of all of the associated objects, forcing a database read.
|
1228
|
+
# An empty Relation is returned if none are found.
|
1124
1229
|
#
|
1125
1230
|
# === Example
|
1126
1231
|
#
|
@@ -1140,6 +1245,7 @@ module ActiveRecord
|
|
1140
1245
|
# * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
|
1141
1246
|
# * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
|
1142
1247
|
# * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save!</tt>)
|
1248
|
+
# * <tt>Firm#clients.reload</tt>
|
1143
1249
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1144
1250
|
#
|
1145
1251
|
# === Scopes
|
@@ -1171,11 +1277,11 @@ module ActiveRecord
|
|
1171
1277
|
# [:class_name]
|
1172
1278
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1173
1279
|
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
1174
|
-
# to the Product class, but if the real class name is SpecialProduct
|
1280
|
+
# to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
|
1175
1281
|
# specify it with this option.
|
1176
1282
|
# [:foreign_key]
|
1177
1283
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1178
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a
|
1284
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
1179
1285
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
1180
1286
|
# [:foreign_type]
|
1181
1287
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1199,20 +1305,20 @@ module ActiveRecord
|
|
1199
1305
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1200
1306
|
#
|
1201
1307
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
1202
|
-
# a
|
1308
|
+
# a #belongs_to, and the records which get deleted are the join records, rather than
|
1203
1309
|
# the associated records.
|
1204
1310
|
# [:counter_cache]
|
1205
1311
|
# This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
|
1206
|
-
# when you customized the name of your <tt>:counter_cache</tt> on the
|
1312
|
+
# when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
|
1207
1313
|
# [:as]
|
1208
|
-
# Specifies a polymorphic interface (See
|
1314
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1209
1315
|
# [:through]
|
1210
1316
|
# Specifies an association through which to perform the query. This can be any other type
|
1211
1317
|
# of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
|
1212
1318
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1213
1319
|
# source reflection.
|
1214
1320
|
#
|
1215
|
-
# If the association on the join model is a
|
1321
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1216
1322
|
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1217
1323
|
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1218
1324
|
# <tt>:through</tt> association directly.
|
@@ -1223,15 +1329,16 @@ module ActiveRecord
|
|
1223
1329
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1224
1330
|
# section above.)
|
1225
1331
|
# [:source]
|
1226
|
-
# Specifies the source association name used by <tt
|
1332
|
+
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1227
1333
|
# Only use it if the name cannot be inferred from the association.
|
1228
1334
|
# <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
1229
1335
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
1230
1336
|
# [:source_type]
|
1231
|
-
# Specifies type of the source association used by <tt
|
1232
|
-
# association is a polymorphic
|
1337
|
+
# Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
|
1338
|
+
# association is a polymorphic #belongs_to.
|
1233
1339
|
# [:validate]
|
1234
|
-
#
|
1340
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1341
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1235
1342
|
# [:autosave]
|
1236
1343
|
# If true, always save the associated objects or destroy them if marked for destruction,
|
1237
1344
|
# when saving the parent object. If false, never save or destroy the associated objects.
|
@@ -1239,18 +1346,23 @@ module ActiveRecord
|
|
1239
1346
|
# +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
|
1240
1347
|
# may need to be explicitly saved in any user-defined +before_save+ callbacks.
|
1241
1348
|
#
|
1242
|
-
# Note that
|
1349
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1350
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1243
1351
|
# [:inverse_of]
|
1244
|
-
# Specifies the name of the
|
1245
|
-
# that is the inverse of this
|
1352
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1353
|
+
# that is the inverse of this #has_many association. Does not work in combination
|
1246
1354
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1247
1355
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1356
|
+
# [:extend]
|
1357
|
+
# Specifies a module or array of modules that will be extended into the association object returned.
|
1358
|
+
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1359
|
+
# association objects.
|
1248
1360
|
#
|
1249
1361
|
# Option examples:
|
1250
|
-
# has_many :comments, -> { order
|
1251
|
-
# has_many :comments, -> { includes
|
1362
|
+
# has_many :comments, -> { order("posted_on") }
|
1363
|
+
# has_many :comments, -> { includes(:author) }
|
1252
1364
|
# has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
|
1253
|
-
# has_many :tracks, -> { order
|
1365
|
+
# has_many :tracks, -> { order("position") }, dependent: :destroy
|
1254
1366
|
# has_many :comments, dependent: :nullify
|
1255
1367
|
# has_many :tags, as: :taggable
|
1256
1368
|
# has_many :reports, -> { readonly }
|
@@ -1262,15 +1374,15 @@ module ActiveRecord
|
|
1262
1374
|
|
1263
1375
|
# Specifies a one-to-one association with another class. This method should only be used
|
1264
1376
|
# if the other class contains the foreign key. If the current class contains the foreign key,
|
1265
|
-
# then you should use
|
1266
|
-
# on when to use
|
1377
|
+
# then you should use #belongs_to instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1378
|
+
# on when to use #has_one and when to use #belongs_to.
|
1267
1379
|
#
|
1268
1380
|
# The following methods for retrieval and query of a single associated object will be added:
|
1269
1381
|
#
|
1270
1382
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
1271
1383
|
# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
|
1272
1384
|
#
|
1273
|
-
# [association
|
1385
|
+
# [association]
|
1274
1386
|
# Returns the associated object. +nil+ is returned if none is found.
|
1275
1387
|
# [association=(associate)]
|
1276
1388
|
# Assigns the associate object, extracts the primary key, sets it as the foreign key,
|
@@ -1285,8 +1397,10 @@ module ActiveRecord
|
|
1285
1397
|
# with +attributes+, linked to this object through a foreign key, and that
|
1286
1398
|
# has already been saved (if it passed the validation).
|
1287
1399
|
# [create_association!(attributes = {})]
|
1288
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1400
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1289
1401
|
# if the record is invalid.
|
1402
|
+
# [reload_association]
|
1403
|
+
# Returns the associated object, forcing a database read.
|
1290
1404
|
#
|
1291
1405
|
# === Example
|
1292
1406
|
#
|
@@ -1296,6 +1410,7 @@ module ActiveRecord
|
|
1296
1410
|
# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
|
1297
1411
|
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
|
1298
1412
|
# * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save!; b</tt>)
|
1413
|
+
# * <tt>Account#reload_beneficiary</tt>
|
1299
1414
|
#
|
1300
1415
|
# === Scopes
|
1301
1416
|
#
|
@@ -1326,9 +1441,11 @@ module ActiveRecord
|
|
1326
1441
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
|
1327
1442
|
# * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
|
1328
1443
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1444
|
+
#
|
1445
|
+
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
1329
1446
|
# [:foreign_key]
|
1330
1447
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1331
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a
|
1448
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
1332
1449
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
1333
1450
|
# [:foreign_type]
|
1334
1451
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1339,31 +1456,33 @@ module ActiveRecord
|
|
1339
1456
|
# [:primary_key]
|
1340
1457
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
1341
1458
|
# [:as]
|
1342
|
-
# Specifies a polymorphic interface (See
|
1459
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1343
1460
|
# [:through]
|
1344
1461
|
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
1345
1462
|
# <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1346
|
-
# source reflection. You can only use a <tt>:through</tt> query through a
|
1347
|
-
# or
|
1463
|
+
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1464
|
+
# or #belongs_to association on the join model.
|
1348
1465
|
# [:source]
|
1349
|
-
# Specifies the source association name used by <tt
|
1466
|
+
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1350
1467
|
# Only use it if the name cannot be inferred from the association.
|
1351
1468
|
# <tt>has_one :favorite, through: :favorites</tt> will look for a
|
1352
1469
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
1353
1470
|
# [:source_type]
|
1354
|
-
# Specifies type of the source association used by <tt
|
1355
|
-
# association is a polymorphic
|
1471
|
+
# Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
|
1472
|
+
# association is a polymorphic #belongs_to.
|
1356
1473
|
# [:validate]
|
1357
|
-
#
|
1474
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1475
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1358
1476
|
# [:autosave]
|
1359
1477
|
# If true, always save the associated object or destroy it if marked for destruction,
|
1360
1478
|
# when saving the parent object. If false, never save or destroy the associated object.
|
1361
1479
|
# By default, only save the associated object if it's a new record.
|
1362
1480
|
#
|
1363
|
-
# Note that
|
1481
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1482
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1364
1483
|
# [:inverse_of]
|
1365
|
-
# Specifies the name of the
|
1366
|
-
# that is the inverse of this
|
1484
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1485
|
+
# that is the inverse of this #has_one association. Does not work in combination
|
1367
1486
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1368
1487
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1369
1488
|
# [:required]
|
@@ -1375,12 +1494,12 @@ module ActiveRecord
|
|
1375
1494
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
1376
1495
|
# has_one :credit_card, dependent: :nullify # updates the associated records foreign
|
1377
1496
|
# # key value to NULL rather than destroying it
|
1378
|
-
# has_one :last_comment, -> { order
|
1379
|
-
# has_one :project_manager, -> { where
|
1497
|
+
# has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
|
1498
|
+
# has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
|
1380
1499
|
# has_one :attachment, as: :attachable
|
1381
1500
|
# has_one :boss, -> { readonly }
|
1382
1501
|
# has_one :club, through: :membership
|
1383
|
-
# has_one :primary_address, -> { where
|
1502
|
+
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1384
1503
|
# has_one :credit_card, required: true
|
1385
1504
|
def has_one(name, scope = nil, options = {})
|
1386
1505
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
@@ -1389,8 +1508,8 @@ module ActiveRecord
|
|
1389
1508
|
|
1390
1509
|
# Specifies a one-to-one association with another class. This method should only be used
|
1391
1510
|
# if this class contains the foreign key. If the other class contains the foreign key,
|
1392
|
-
# then you should use
|
1393
|
-
# on when to use
|
1511
|
+
# then you should use #has_one instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1512
|
+
# on when to use #has_one and when to use #belongs_to.
|
1394
1513
|
#
|
1395
1514
|
# Methods will be added for retrieval and query for a single associated object, for which
|
1396
1515
|
# this object holds an id:
|
@@ -1398,7 +1517,7 @@ module ActiveRecord
|
|
1398
1517
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
1399
1518
|
# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
|
1400
1519
|
#
|
1401
|
-
# [association
|
1520
|
+
# [association]
|
1402
1521
|
# Returns the associated object. +nil+ is returned if none is found.
|
1403
1522
|
# [association=(associate)]
|
1404
1523
|
# Assigns the associate object, extracts the primary key, and sets it as the foreign key.
|
@@ -1410,8 +1529,10 @@ module ActiveRecord
|
|
1410
1529
|
# with +attributes+, linked to this object through a foreign key, and that
|
1411
1530
|
# has already been saved (if it passed the validation).
|
1412
1531
|
# [create_association!(attributes = {})]
|
1413
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1532
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1414
1533
|
# if the record is invalid.
|
1534
|
+
# [reload_association]
|
1535
|
+
# Returns the associated object, forcing a database read.
|
1415
1536
|
#
|
1416
1537
|
# === Example
|
1417
1538
|
#
|
@@ -1421,6 +1542,7 @@ module ActiveRecord
|
|
1421
1542
|
# * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
|
1422
1543
|
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
1423
1544
|
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1545
|
+
# * <tt>Post#reload_author</tt>
|
1424
1546
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1425
1547
|
#
|
1426
1548
|
# === Scopes
|
@@ -1430,7 +1552,7 @@ module ActiveRecord
|
|
1430
1552
|
# when you access the associated object.
|
1431
1553
|
#
|
1432
1554
|
# Scope examples:
|
1433
|
-
# belongs_to :
|
1555
|
+
# belongs_to :firm, -> { where(id: 2) }
|
1434
1556
|
# belongs_to :user, -> { joins(:friends) }
|
1435
1557
|
# belongs_to :level, ->(level) { where("game_level > ?", level.current) }
|
1436
1558
|
#
|
@@ -1457,12 +1579,12 @@ module ActiveRecord
|
|
1457
1579
|
# [:dependent]
|
1458
1580
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1459
1581
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1460
|
-
# This option should not be specified when
|
1461
|
-
# a
|
1582
|
+
# This option should not be specified when #belongs_to is used in conjunction with
|
1583
|
+
# a #has_many relationship on another class because of the potential to leave
|
1462
1584
|
# orphaned records behind.
|
1463
1585
|
# [:counter_cache]
|
1464
|
-
# Caches the number of belonging objects on the associate class through the use of
|
1465
|
-
# and
|
1586
|
+
# Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
|
1587
|
+
# and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
|
1466
1588
|
# class is created and decremented when it's destroyed. This requires that a column
|
1467
1589
|
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
1468
1590
|
# is used on the associate class (such as a Post class) - that is the migration for
|
@@ -1477,27 +1599,35 @@ module ActiveRecord
|
|
1477
1599
|
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
|
1478
1600
|
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
|
1479
1601
|
# [:validate]
|
1480
|
-
#
|
1602
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1603
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1481
1604
|
# [:autosave]
|
1482
1605
|
# If true, always save the associated object or destroy it if marked for destruction, when
|
1483
1606
|
# saving the parent object.
|
1484
1607
|
# If false, never save or destroy the associated object.
|
1485
1608
|
# By default, only save the associated object if it's a new record.
|
1486
1609
|
#
|
1487
|
-
# Note that
|
1610
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1611
|
+
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1488
1612
|
# [:touch]
|
1489
1613
|
# If true, the associated object will be touched (the updated_at/on attributes set to current time)
|
1490
1614
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1491
1615
|
# will be updated with the current time in addition to the updated_at/on attribute.
|
1616
|
+
# Please note that with touching no validation is performed and only the +after_touch+,
|
1617
|
+
# +after_commit+ and +after_rollback+ callbacks are executed.
|
1492
1618
|
# [:inverse_of]
|
1493
|
-
# Specifies the name of the
|
1494
|
-
# object that is the inverse of this
|
1619
|
+
# Specifies the name of the #has_one or #has_many association on the associated
|
1620
|
+
# object that is the inverse of this #belongs_to association. Does not work in
|
1495
1621
|
# combination with the <tt>:polymorphic</tt> options.
|
1496
1622
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1623
|
+
# [:optional]
|
1624
|
+
# When set to +true+, the association will not have its presence validated.
|
1497
1625
|
# [:required]
|
1498
1626
|
# When set to +true+, the association will also have its presence validated.
|
1499
1627
|
# This will validate the association itself, not the id. You can use
|
1500
1628
|
# +:inverse_of+ to avoid an extra query during validation.
|
1629
|
+
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
|
1630
|
+
# you don't want to have association presence validated, use <tt>optional: true</tt>.
|
1501
1631
|
#
|
1502
1632
|
# Option examples:
|
1503
1633
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1508,9 +1638,9 @@ module ActiveRecord
|
|
1508
1638
|
# belongs_to :attachable, polymorphic: true
|
1509
1639
|
# belongs_to :project, -> { readonly }
|
1510
1640
|
# belongs_to :post, counter_cache: true
|
1511
|
-
# belongs_to :
|
1641
|
+
# belongs_to :comment, touch: true
|
1512
1642
|
# belongs_to :company, touch: :employees_last_updated_at
|
1513
|
-
# belongs_to :
|
1643
|
+
# belongs_to :user, optional: true
|
1514
1644
|
def belongs_to(name, scope = nil, options = {})
|
1515
1645
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1516
1646
|
Reflection.add_reflection self, name, reflection
|
@@ -1533,12 +1663,9 @@ module ActiveRecord
|
|
1533
1663
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1534
1664
|
# join table with a migration such as this:
|
1535
1665
|
#
|
1536
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
|
1666
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[5.0]
|
1537
1667
|
# def change
|
1538
|
-
#
|
1539
|
-
# t.integer :developer_id
|
1540
|
-
# t.integer :project_id
|
1541
|
-
# end
|
1668
|
+
# create_join_table :developers, :projects
|
1542
1669
|
# end
|
1543
1670
|
# end
|
1544
1671
|
#
|
@@ -1551,9 +1678,9 @@ module ActiveRecord
|
|
1551
1678
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
1552
1679
|
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
|
1553
1680
|
#
|
1554
|
-
# [collection
|
1555
|
-
# Returns
|
1556
|
-
# An empty
|
1681
|
+
# [collection]
|
1682
|
+
# Returns a Relation of all the associated objects.
|
1683
|
+
# An empty Relation is returned if none are found.
|
1557
1684
|
# [collection<<(object, ...)]
|
1558
1685
|
# Adds one or more objects to the collection by creating associations in the join table
|
1559
1686
|
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
|
@@ -1580,10 +1707,10 @@ module ActiveRecord
|
|
1580
1707
|
# [collection.find(id)]
|
1581
1708
|
# Finds an associated object responding to the +id+ and that
|
1582
1709
|
# meets the condition that it has to be associated with this object.
|
1583
|
-
# Uses the same rules as
|
1710
|
+
# Uses the same rules as ActiveRecord::FinderMethods#find.
|
1584
1711
|
# [collection.exists?(...)]
|
1585
1712
|
# Checks whether an associated object with the given conditions exists.
|
1586
|
-
# Uses the same rules as
|
1713
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1587
1714
|
# [collection.build(attributes = {})]
|
1588
1715
|
# Returns a new object of the collection type that has been instantiated
|
1589
1716
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
@@ -1591,6 +1718,9 @@ module ActiveRecord
|
|
1591
1718
|
# Returns a new object of the collection type that has been instantiated
|
1592
1719
|
# with +attributes+, linked to this object through the join table, and that has already been
|
1593
1720
|
# saved (if it passed the validation).
|
1721
|
+
# [collection.reload]
|
1722
|
+
# Returns a Relation of all of the associated objects, forcing a database read.
|
1723
|
+
# An empty Relation is returned if none are found.
|
1594
1724
|
#
|
1595
1725
|
# === Example
|
1596
1726
|
#
|
@@ -1609,6 +1739,7 @@ module ActiveRecord
|
|
1609
1739
|
# * <tt>Developer#projects.exists?(...)</tt>
|
1610
1740
|
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("developer_id" => id)</tt>)
|
1611
1741
|
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
|
1742
|
+
# * <tt>Developer#projects.reload</tt>
|
1612
1743
|
# The declaration may include an +options+ hash to specialize the behavior of the association.
|
1613
1744
|
#
|
1614
1745
|
# === Scopes
|
@@ -1618,7 +1749,7 @@ module ActiveRecord
|
|
1618
1749
|
# query when you access the associated collection.
|
1619
1750
|
#
|
1620
1751
|
# Scope examples:
|
1621
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1752
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1622
1753
|
# has_and_belongs_to_many :categories, ->(category) {
|
1623
1754
|
# where("default_category = ?", category.name)
|
1624
1755
|
# }
|
@@ -1647,32 +1778,32 @@ module ActiveRecord
|
|
1647
1778
|
# [:join_table]
|
1648
1779
|
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
1649
1780
|
# <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
|
1650
|
-
# MUST be declared underneath any
|
1781
|
+
# MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
|
1651
1782
|
# [:foreign_key]
|
1652
1783
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1653
1784
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1654
|
-
# a
|
1785
|
+
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
1655
1786
|
# default <tt>:foreign_key</tt>.
|
1656
1787
|
# [:association_foreign_key]
|
1657
1788
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1658
1789
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
1659
|
-
# So if a Person class makes a
|
1790
|
+
# So if a Person class makes a #has_and_belongs_to_many association to Project,
|
1660
1791
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
1661
|
-
# [:readonly]
|
1662
|
-
# If true, all the associated objects are readonly through the association.
|
1663
1792
|
# [:validate]
|
1664
|
-
#
|
1793
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1794
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1665
1795
|
# [:autosave]
|
1666
1796
|
# If true, always save the associated objects or destroy them if marked for destruction, when
|
1667
1797
|
# saving the parent object.
|
1668
1798
|
# If false, never save or destroy the associated objects.
|
1669
1799
|
# By default, only save associated objects that are new records.
|
1670
1800
|
#
|
1671
|
-
# Note that
|
1801
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1802
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1672
1803
|
#
|
1673
1804
|
# Option examples:
|
1674
1805
|
# has_and_belongs_to_many :projects
|
1675
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1806
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1676
1807
|
# has_and_belongs_to_many :nations, class_name: "Country"
|
1677
1808
|
# has_and_belongs_to_many :categories, join_table: "prods_cats"
|
1678
1809
|
# has_and_belongs_to_many :categories, -> { readonly }
|
@@ -1688,16 +1819,14 @@ module ActiveRecord
|
|
1688
1819
|
|
1689
1820
|
join_model = builder.through_model
|
1690
1821
|
|
1691
|
-
# FIXME: we should move this to the internal constants. Also people
|
1692
|
-
# should never directly access this constant so I'm not happy about
|
1693
|
-
# setting it.
|
1694
1822
|
const_set join_model.name, join_model
|
1823
|
+
private_constant join_model.name
|
1695
1824
|
|
1696
1825
|
middle_reflection = builder.middle_reflection join_model
|
1697
1826
|
|
1698
1827
|
Builder::HasMany.define_callbacks self, middle_reflection
|
1699
1828
|
Reflection.add_reflection self, middle_reflection.name, middle_reflection
|
1700
|
-
middle_reflection.parent_reflection =
|
1829
|
+
middle_reflection.parent_reflection = habtm_reflection
|
1701
1830
|
|
1702
1831
|
include Module.new {
|
1703
1832
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -1718,7 +1847,7 @@ module ActiveRecord
|
|
1718
1847
|
end
|
1719
1848
|
|
1720
1849
|
has_many name, scope, hm_options, &extension
|
1721
|
-
self._reflections[name.to_s].parent_reflection =
|
1850
|
+
self._reflections[name.to_s].parent_reflection = habtm_reflection
|
1722
1851
|
end
|
1723
1852
|
end
|
1724
1853
|
end
|