activerecord 5.1.7 → 5.2.8.1
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 +629 -661
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +30 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attributes.rb +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +15 -1
- data/lib/active_record/collection_cache_key.rb +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +51 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +42 -3
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +14 -17
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/model_schema.rb +16 -21
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +80 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/calculations.rb +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +120 -214
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -7
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +35 -5
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +3 -1
- metadata +26 -39
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -26,7 +26,7 @@ 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
|
29
|
+
id bigint NOT NULL auto_increment,
|
30
30
|
name varchar(255),
|
31
31
|
PRIMARY KEY (id)
|
32
32
|
);
|
@@ -162,7 +162,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
162
162
|
== Philosophy
|
163
163
|
|
164
164
|
Active Record is an implementation of the object-relational mapping (ORM)
|
165
|
-
pattern[
|
165
|
+
pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
166
166
|
name described by Martin Fowler:
|
167
167
|
|
168
168
|
"An object that wraps a row in a database table or view,
|
@@ -192,14 +192,14 @@ The latest version of Active Record can be installed with RubyGems:
|
|
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-2-stable/activerecord
|
196
196
|
|
197
197
|
|
198
198
|
== License
|
199
199
|
|
200
200
|
Active Record is released under the MIT license:
|
201
201
|
|
202
|
-
*
|
202
|
+
* https://opensource.org/licenses/MIT
|
203
203
|
|
204
204
|
|
205
205
|
== Support
|
@@ -208,7 +208,7 @@ API documentation is at:
|
|
208
208
|
|
209
209
|
* http://api.rubyonrails.org
|
210
210
|
|
211
|
-
Bug reports
|
211
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
212
212
|
|
213
213
|
* https://github.com/rails/rails/issues
|
214
214
|
|
data/examples/performance.rb
CHANGED
data/examples/simple.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
3
5
|
module Aggregations
|
@@ -33,7 +35,7 @@ module ActiveRecord
|
|
33
35
|
# the database).
|
34
36
|
#
|
35
37
|
# class Customer < ActiveRecord::Base
|
36
|
-
# composed_of :balance, class_name: "Money", mapping: %w(amount
|
38
|
+
# composed_of :balance, class_name: "Money", mapping: %w(balance amount)
|
37
39
|
# composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
|
38
40
|
# end
|
39
41
|
#
|
@@ -175,9 +177,9 @@ module ActiveRecord
|
|
175
177
|
#
|
176
178
|
# Once a #composed_of relationship is specified for a model, records can be loaded from the database
|
177
179
|
# by specifying an instance of the value object in the conditions hash. The following example
|
178
|
-
# finds all customers with +
|
180
|
+
# finds all customers with +address_street+ equal to "May Street" and +address_city+ equal to "Chicago":
|
179
181
|
#
|
180
|
-
# Customer.where(
|
182
|
+
# Customer.where(address: Address.new("May Street", "Chicago"))
|
181
183
|
#
|
182
184
|
module ClassMethods
|
183
185
|
# Adds reader and writer methods for manipulating a value object:
|
@@ -210,8 +212,7 @@ module ActiveRecord
|
|
210
212
|
#
|
211
213
|
# Option examples:
|
212
214
|
# composed_of :temperature, mapping: %w(reading celsius)
|
213
|
-
# composed_of :balance, class_name: "Money", mapping: %w(balance amount)
|
214
|
-
# converter: Proc.new { |balance| balance.to_money }
|
215
|
+
# composed_of :balance, class_name: "Money", mapping: %w(balance amount)
|
215
216
|
# composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
|
216
217
|
# composed_of :gps_location
|
217
218
|
# composed_of :gps_location, allow_nil: true
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class AssociationRelation < Relation
|
3
|
-
def initialize(klass,
|
4
|
-
super(klass
|
5
|
+
def initialize(klass, association)
|
6
|
+
super(klass)
|
5
7
|
@association = association
|
6
8
|
end
|
7
9
|
|
@@ -29,9 +31,9 @@ module ActiveRecord
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def exec_queries
|
32
|
-
super do |
|
33
|
-
@association.
|
34
|
-
yield
|
34
|
+
super do |record|
|
35
|
+
@association.set_inverse_instance_from_queries(record)
|
36
|
+
yield record if block_given?
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -1,51 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/conversions"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
7
|
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
6
8
|
class AliasTracker # :nodoc:
|
7
|
-
|
8
|
-
|
9
|
-
def self.create(connection, initial_table)
|
10
|
-
aliases = Hash.new(0)
|
11
|
-
aliases[initial_table] = 1
|
12
|
-
new(connection, aliases)
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.create_with_joins(connection, initial_table, joins)
|
9
|
+
def self.create(connection, initial_table, joins)
|
16
10
|
if joins.empty?
|
17
|
-
|
11
|
+
aliases = Hash.new(0)
|
18
12
|
else
|
19
13
|
aliases = Hash.new { |h, k|
|
20
14
|
h[k] = initial_count_for(connection, k, joins)
|
21
15
|
}
|
22
|
-
aliases[initial_table] = 1
|
23
|
-
new(connection, aliases)
|
24
16
|
end
|
17
|
+
aliases[initial_table] = 1
|
18
|
+
new(connection, aliases)
|
25
19
|
end
|
26
20
|
|
27
21
|
def self.initial_count_for(connection, name, table_joins)
|
28
|
-
|
29
|
-
quoted_name = connection.quote_table_name(name).downcase
|
22
|
+
quoted_name = nil
|
30
23
|
|
31
24
|
counts = table_joins.map do |join|
|
32
25
|
if join.is_a?(Arel::Nodes::StringJoin)
|
26
|
+
# quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
27
|
+
quoted_name ||= connection.quote_table_name(name)
|
28
|
+
|
33
29
|
# Table names + table aliases
|
34
|
-
join.left.
|
35
|
-
/
|
30
|
+
join.left.scan(
|
31
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
|
36
32
|
).size
|
37
|
-
elsif join.
|
38
|
-
join.left.
|
33
|
+
elsif join.is_a?(Arel::Nodes::Join)
|
34
|
+
join.left.name == name ? 1 : 0
|
35
|
+
elsif join.is_a?(Hash)
|
36
|
+
join[name]
|
39
37
|
else
|
40
|
-
|
41
|
-
#
|
42
|
-
# activerecord/test/cases/associations/cascaded_eager_loading_test.rb:37
|
43
|
-
# with :posts
|
44
|
-
#
|
45
|
-
# activerecord/test/cases/associations/eager_test.rb:1133
|
46
|
-
# with :comments
|
47
|
-
#
|
48
|
-
0
|
38
|
+
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
49
39
|
end
|
50
40
|
end
|
51
41
|
|
@@ -79,6 +69,8 @@ module ActiveRecord
|
|
79
69
|
end
|
80
70
|
end
|
81
71
|
|
72
|
+
attr_reader :aliases
|
73
|
+
|
82
74
|
private
|
83
75
|
|
84
76
|
def truncate(name)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -17,7 +19,6 @@ module ActiveRecord
|
|
17
19
|
# HasManyThroughAssociation + ThroughAssociation
|
18
20
|
class Association #:nodoc:
|
19
21
|
attr_reader :owner, :target, :reflection
|
20
|
-
attr_accessor :inversed
|
21
22
|
|
22
23
|
delegate :options, to: :reflection
|
23
24
|
|
@@ -30,14 +31,6 @@ module ActiveRecord
|
|
30
31
|
reset_scope
|
31
32
|
end
|
32
33
|
|
33
|
-
# Returns the name of the table of the associated class:
|
34
|
-
#
|
35
|
-
# post.comments.aliased_table_name # => "comments"
|
36
|
-
#
|
37
|
-
def aliased_table_name
|
38
|
-
klass.table_name
|
39
|
-
end
|
40
|
-
|
41
34
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
35
|
def reset
|
43
36
|
@loaded = false
|
@@ -73,7 +66,7 @@ module ActiveRecord
|
|
73
66
|
#
|
74
67
|
# Note that if the target has not been loaded, it is not considered stale.
|
75
68
|
def stale_target?
|
76
|
-
|
69
|
+
!@inversed && loaded? && @stale_state != stale_state
|
77
70
|
end
|
78
71
|
|
79
72
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -94,7 +87,7 @@ module ActiveRecord
|
|
94
87
|
# actually gets built.
|
95
88
|
def association_scope
|
96
89
|
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self
|
90
|
+
@association_scope ||= AssociationScope.scope(self)
|
98
91
|
end
|
99
92
|
end
|
100
93
|
|
@@ -104,23 +97,32 @@ module ActiveRecord
|
|
104
97
|
|
105
98
|
# Set the inverse association, if possible
|
106
99
|
def set_inverse_instance(record)
|
107
|
-
if
|
108
|
-
inverse
|
109
|
-
|
110
|
-
|
100
|
+
if inverse = inverse_association_for(record)
|
101
|
+
inverse.inversed_from(owner)
|
102
|
+
end
|
103
|
+
record
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_inverse_instance_from_queries(record)
|
107
|
+
if inverse = inverse_association_for(record)
|
108
|
+
inverse.inversed_from_queries(owner)
|
111
109
|
end
|
112
110
|
record
|
113
111
|
end
|
114
112
|
|
115
113
|
# Remove the inverse association, if possible
|
116
114
|
def remove_inverse_instance(record)
|
117
|
-
if
|
118
|
-
inverse
|
119
|
-
inverse.target = nil
|
120
|
-
inverse.inversed = false
|
115
|
+
if inverse = inverse_association_for(record)
|
116
|
+
inverse.inversed_from(nil)
|
121
117
|
end
|
122
118
|
end
|
123
119
|
|
120
|
+
def inversed_from(record)
|
121
|
+
self.target = record
|
122
|
+
@inversed = !!record
|
123
|
+
end
|
124
|
+
alias :inversed_from_queries :inversed_from
|
125
|
+
|
124
126
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
125
127
|
# polymorphic_type field on the owner.
|
126
128
|
def klass
|
@@ -130,14 +132,14 @@ module ActiveRecord
|
|
130
132
|
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
131
133
|
# through association's scope)
|
132
134
|
def target_scope
|
133
|
-
AssociationRelation.create(klass,
|
135
|
+
AssociationRelation.create(klass, self).merge!(klass.all)
|
134
136
|
end
|
135
137
|
|
136
138
|
def extensions
|
137
139
|
extensions = klass.default_extensions | reflection.extensions
|
138
140
|
|
139
|
-
if
|
140
|
-
extensions |= klass.unscoped
|
141
|
+
if reflection.scope
|
142
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
141
143
|
end
|
142
144
|
|
143
145
|
extensions
|
@@ -162,17 +164,9 @@ module ActiveRecord
|
|
162
164
|
reset
|
163
165
|
end
|
164
166
|
|
165
|
-
|
166
|
-
if sql.respond_to?(:to_proc)
|
167
|
-
owner.instance_exec(record, &sql)
|
168
|
-
else
|
169
|
-
sql
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# We can't dump @reflection since it contains the scope proc
|
167
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
174
168
|
def marshal_dump
|
175
|
-
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
169
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
176
170
|
[@reflection.name, ivars]
|
177
171
|
end
|
178
172
|
|
@@ -187,8 +181,8 @@ module ActiveRecord
|
|
187
181
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
188
182
|
assigned_keys = record.changed_attribute_names_to_save
|
189
183
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
190
|
-
attributes =
|
191
|
-
record.
|
184
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
185
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
192
186
|
set_inverse_instance(record)
|
193
187
|
end
|
194
188
|
|
@@ -201,6 +195,9 @@ module ActiveRecord
|
|
201
195
|
end
|
202
196
|
|
203
197
|
private
|
198
|
+
def scope_for_create
|
199
|
+
scope.scope_for_create
|
200
|
+
end
|
204
201
|
|
205
202
|
def find_target?
|
206
203
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -212,8 +209,8 @@ module ActiveRecord
|
|
212
209
|
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
213
210
|
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
214
211
|
|
215
|
-
if reflection.
|
216
|
-
attributes[reflection.type] = owner.class.
|
212
|
+
if reflection.type
|
213
|
+
attributes[reflection.type] = owner.class.polymorphic_name
|
217
214
|
end
|
218
215
|
end
|
219
216
|
|
@@ -251,6 +248,12 @@ module ActiveRecord
|
|
251
248
|
end
|
252
249
|
end
|
253
250
|
|
251
|
+
def inverse_association_for(record)
|
252
|
+
if invertible_for?(record)
|
253
|
+
record.association(inverse_reflection_for(record).name)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
254
257
|
# Can be redefined by subclasses, notably polymorphic belongs_to
|
255
258
|
# The record parameter is necessary to support polymorphic inverses as we must check for
|
256
259
|
# the association in the specific class of the record.
|
@@ -280,11 +283,12 @@ module ActiveRecord
|
|
280
283
|
def build_record(attributes)
|
281
284
|
reflection.build_association(attributes) do |record|
|
282
285
|
initialize_attributes(record, attributes)
|
286
|
+
yield(record) if block_given?
|
283
287
|
end
|
284
288
|
end
|
285
289
|
|
286
290
|
# Returns true if statement cache should be skipped on the association reader.
|
287
|
-
def skip_statement_cache?
|
291
|
+
def skip_statement_cache?(scope)
|
288
292
|
reflection.has_scope? ||
|
289
293
|
scope.eager_loading? ||
|
290
294
|
klass.scope_attributes? ||
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class AssociationScope #:nodoc:
|
4
|
-
def self.scope(association
|
5
|
-
INSTANCE.scope(association
|
6
|
+
def self.scope(association)
|
7
|
+
INSTANCE.scope(association)
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.create(&block)
|
@@ -16,20 +18,15 @@ module ActiveRecord
|
|
16
18
|
|
17
19
|
INSTANCE = create
|
18
20
|
|
19
|
-
def scope(association
|
21
|
+
def scope(association)
|
20
22
|
klass = association.klass
|
21
23
|
reflection = association.reflection
|
22
24
|
scope = klass.unscoped
|
23
25
|
owner = association.owner
|
24
|
-
|
25
|
-
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
|
26
|
+
chain = get_chain(reflection, association, scope.alias_tracker)
|
26
27
|
|
27
28
|
scope.extending! reflection.extensions
|
28
|
-
add_constraints(scope, owner,
|
29
|
-
end
|
30
|
-
|
31
|
-
def join_type
|
32
|
-
Arel::Nodes::InnerJoin
|
29
|
+
add_constraints(scope, owner, chain)
|
33
30
|
end
|
34
31
|
|
35
32
|
def self.get_bind_values(owner, chain)
|
@@ -38,12 +35,12 @@ module ActiveRecord
|
|
38
35
|
|
39
36
|
binds << last_reflection.join_id_for(owner)
|
40
37
|
if last_reflection.type
|
41
|
-
binds << owner.class.
|
38
|
+
binds << owner.class.polymorphic_name
|
42
39
|
end
|
43
40
|
|
44
41
|
chain.each_cons(2).each do |reflection, next_reflection|
|
45
42
|
if reflection.type
|
46
|
-
binds << next_reflection.klass.
|
43
|
+
binds << next_reflection.klass.polymorphic_name
|
47
44
|
end
|
48
45
|
end
|
49
46
|
binds
|
@@ -57,19 +54,20 @@ module ActiveRecord
|
|
57
54
|
|
58
55
|
private
|
59
56
|
def join(table, constraint)
|
60
|
-
table.create_join(table, table.create_on(constraint)
|
57
|
+
table.create_join(table, table.create_on(constraint))
|
61
58
|
end
|
62
59
|
|
63
|
-
def last_chain_scope(scope,
|
60
|
+
def last_chain_scope(scope, reflection, owner)
|
64
61
|
join_keys = reflection.join_keys
|
65
62
|
key = join_keys.key
|
66
63
|
foreign_key = join_keys.foreign_key
|
67
64
|
|
65
|
+
table = reflection.aliased_table
|
68
66
|
value = transform_value(owner[foreign_key])
|
69
67
|
scope = apply_scope(scope, table, key, value)
|
70
68
|
|
71
69
|
if reflection.type
|
72
|
-
polymorphic_type = transform_value(owner.class.
|
70
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
73
71
|
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
74
72
|
end
|
75
73
|
|
@@ -80,15 +78,17 @@ module ActiveRecord
|
|
80
78
|
value_transformation.call(value)
|
81
79
|
end
|
82
80
|
|
83
|
-
def next_chain_scope(scope,
|
81
|
+
def next_chain_scope(scope, reflection, next_reflection)
|
84
82
|
join_keys = reflection.join_keys
|
85
83
|
key = join_keys.key
|
86
84
|
foreign_key = join_keys.foreign_key
|
87
85
|
|
86
|
+
table = reflection.aliased_table
|
87
|
+
foreign_table = next_reflection.aliased_table
|
88
88
|
constraint = table[key].eq(foreign_table[foreign_key])
|
89
89
|
|
90
90
|
if reflection.type
|
91
|
-
value = transform_value(next_reflection.klass.
|
91
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
92
92
|
scope = apply_scope(scope, table, reflection.type, value)
|
93
93
|
end
|
94
94
|
|
@@ -96,12 +96,11 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
|
98
98
|
class ReflectionProxy < SimpleDelegator # :nodoc:
|
99
|
-
|
100
|
-
attr_reader :alias_name
|
99
|
+
attr_reader :aliased_table
|
101
100
|
|
102
|
-
def initialize(reflection,
|
101
|
+
def initialize(reflection, aliased_table)
|
103
102
|
super(reflection)
|
104
|
-
@
|
103
|
+
@aliased_table = aliased_table
|
105
104
|
end
|
106
105
|
|
107
106
|
def all_includes; nil; end
|
@@ -109,43 +108,34 @@ module ActiveRecord
|
|
109
108
|
|
110
109
|
def get_chain(reflection, association, tracker)
|
111
110
|
name = reflection.name
|
112
|
-
|
113
|
-
previous_reflection = runtime_reflection
|
111
|
+
chain = [Reflection::RuntimeReflection.new(reflection, association)]
|
114
112
|
reflection.chain.drop(1).each do |refl|
|
115
|
-
|
113
|
+
aliased_table = tracker.aliased_table_for(
|
116
114
|
refl.table_name,
|
117
115
|
refl.alias_candidate(name),
|
118
116
|
refl.klass.type_caster
|
119
117
|
)
|
120
|
-
|
121
|
-
previous_reflection.next = proxy
|
122
|
-
previous_reflection = proxy
|
118
|
+
chain << ReflectionProxy.new(refl, aliased_table)
|
123
119
|
end
|
124
|
-
|
120
|
+
chain
|
125
121
|
end
|
126
122
|
|
127
|
-
def add_constraints(scope, owner,
|
128
|
-
|
129
|
-
table = owner_reflection.alias_name
|
130
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner)
|
131
|
-
|
132
|
-
reflection = chain_head
|
133
|
-
while reflection
|
134
|
-
table = reflection.alias_name
|
135
|
-
next_reflection = reflection.next
|
123
|
+
def add_constraints(scope, owner, chain)
|
124
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
136
125
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
126
|
+
chain.each_cons(2) do |reflection, next_reflection|
|
127
|
+
scope = next_chain_scope(scope, reflection, next_reflection)
|
128
|
+
end
|
141
129
|
|
130
|
+
chain_head = chain.first
|
131
|
+
chain.reverse_each do |reflection|
|
142
132
|
# Exclude the scope of the association itself, because that
|
143
133
|
# was already merged in the #scope method.
|
144
134
|
reflection.constraints.each do |scope_chain_item|
|
145
|
-
item = eval_scope(reflection
|
135
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
146
136
|
|
147
|
-
if scope_chain_item ==
|
148
|
-
scope.merge! item.except(:where, :includes)
|
137
|
+
if scope_chain_item == chain_head.scope
|
138
|
+
scope.merge! item.except(:where, :includes, :unscope, :order)
|
149
139
|
end
|
150
140
|
|
151
141
|
reflection.all_includes do
|
@@ -154,10 +144,8 @@ module ActiveRecord
|
|
154
144
|
|
155
145
|
scope.unscope!(*item.unscope_values)
|
156
146
|
scope.where_clause += item.where_clause
|
157
|
-
scope.order_values
|
147
|
+
scope.order_values = item.order_values | scope.order_values
|
158
148
|
end
|
159
|
-
|
160
|
-
reflection = next_reflection
|
161
149
|
end
|
162
150
|
|
163
151
|
scope
|
@@ -171,9 +159,9 @@ module ActiveRecord
|
|
171
159
|
end
|
172
160
|
end
|
173
161
|
|
174
|
-
def eval_scope(
|
175
|
-
|
176
|
-
|
162
|
+
def eval_scope(reflection, scope, owner)
|
163
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
164
|
+
relation.instance_exec(owner, &scope) || relation
|
177
165
|
end
|
178
166
|
end
|
179
167
|
end
|
@@ -1,26 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Belongs To Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Belongs To Association
|
4
6
|
class BelongsToAssociation < SingularAssociation #:nodoc:
|
5
7
|
def handle_dependency
|
6
|
-
|
8
|
+
return unless load_target
|
9
|
+
|
10
|
+
case options[:dependent]
|
11
|
+
when :destroy
|
12
|
+
target.destroy
|
13
|
+
raise ActiveRecord::Rollback unless target.destroyed?
|
14
|
+
else
|
15
|
+
target.send(options[:dependent])
|
16
|
+
end
|
7
17
|
end
|
8
18
|
|
9
19
|
def replace(record)
|
10
20
|
if record
|
11
21
|
raise_on_type_mismatch!(record)
|
12
22
|
update_counters_on_replace(record)
|
13
|
-
replace_keys(record)
|
14
23
|
set_inverse_instance(record)
|
15
24
|
@updated = true
|
16
25
|
else
|
17
26
|
decrement_counters
|
18
|
-
remove_keys
|
19
27
|
end
|
20
28
|
|
29
|
+
replace_keys(record)
|
30
|
+
|
21
31
|
self.target = record
|
22
32
|
end
|
23
33
|
|
34
|
+
def inversed_from(record)
|
35
|
+
replace_keys(record)
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
24
39
|
def default(&block)
|
25
40
|
writer(owner.instance_exec(&block)) if reader.nil?
|
26
41
|
end
|
@@ -42,6 +57,10 @@ module ActiveRecord
|
|
42
57
|
update_counters(1)
|
43
58
|
end
|
44
59
|
|
60
|
+
def target_changed?
|
61
|
+
owner.saved_change_to_attribute?(reflection.foreign_key)
|
62
|
+
end
|
63
|
+
|
45
64
|
private
|
46
65
|
|
47
66
|
def update_counters(by)
|
@@ -72,15 +91,15 @@ module ActiveRecord
|
|
72
91
|
|
73
92
|
# Checks whether record is different to the current target, without loading it
|
74
93
|
def different_target?(record)
|
75
|
-
record.
|
94
|
+
record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key)
|
76
95
|
end
|
77
96
|
|
78
97
|
def replace_keys(record)
|
79
|
-
owner[reflection.foreign_key] = record._read_attribute(
|
98
|
+
owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record)) : nil
|
80
99
|
end
|
81
100
|
|
82
|
-
def
|
83
|
-
|
101
|
+
def primary_key(record)
|
102
|
+
reflection.association_primary_key(record.class)
|
84
103
|
end
|
85
104
|
|
86
105
|
def foreign_key_present?
|