activerecord 5.1.0 → 5.2.0.rc1
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 +5 -5
- data/CHANGELOG.md +410 -530
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- 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 +4 -2
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +20 -21
- data/lib/active_record/associations/association_scope.rb +49 -49
- data/lib/active_record/associations/belongs_to_association.rb +12 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +10 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- 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 +50 -41
- data/lib/active_record/associations/collection_proxy.rb +22 -39
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +12 -18
- data/lib/active_record/associations/has_one_association.rb +5 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/join_dependency.rb +27 -44
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +68 -76
- data/lib/active_record/attribute_assignment.rb +2 -0
- 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 +24 -214
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- 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 +22 -19
- data/lib/active_record/attribute_methods.rb +48 -12
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +8 -11
- 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 +2 -0
- data/lib/active_record/collection_cache_key.rb +14 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
- data/lib/active_record/connection_adapters/column.rb +4 -2
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
- 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 -23
- 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 +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- 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_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- 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 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- 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 +2 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -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 +269 -126
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
- 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 +18 -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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
- 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 +39 -60
- data/lib/active_record/counter_cache.rb +3 -2
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +17 -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 +4 -2
- data/lib/active_record/inheritance.rb +9 -9
- 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 +8 -6
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +74 -22
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +181 -137
- data/lib/active_record/model_schema.rb +73 -58
- 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 +153 -18
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +61 -3
- 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 +47 -37
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +131 -204
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/calculations.rb +58 -20
- data/lib/active_record/relation/delegation.rb +10 -29
- data/lib/active_record/relation/finder_methods.rb +74 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +51 -20
- 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 +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +53 -78
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +101 -95
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -1
- data/lib/active_record/relation/where_clause.rb +65 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +99 -202
- 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 +10 -7
- data/lib/active_record/scoping/named.rb +38 -12
- data/lib/active_record/scoping.rb +12 -10
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- 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 +37 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -5
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- 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 +25 -37
- 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 -113
- data/lib/active_record/attribute_set/builder.rb +0 -124
- 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 -33
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,
|
@@ -199,7 +199,7 @@ Source code can be downloaded as part of the Rails project on GitHub:
|
|
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
|
|
@@ -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, type_caster)
|
10
|
-
aliases = Hash.new(0)
|
11
|
-
aliases[initial_table] = 1
|
12
|
-
new connection, aliases, type_caster
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.create_with_joins(connection, initial_table, joins, type_caster)
|
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, type_caster
|
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.fetch(name, 0)
|
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
|
|
@@ -53,17 +43,16 @@ module ActiveRecord
|
|
53
43
|
end
|
54
44
|
|
55
45
|
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
56
|
-
def initialize(connection, aliases
|
46
|
+
def initialize(connection, aliases)
|
57
47
|
@aliases = aliases
|
58
48
|
@connection = connection
|
59
|
-
@type_caster = type_caster
|
60
49
|
end
|
61
50
|
|
62
|
-
def aliased_table_for(table_name, aliased_name)
|
51
|
+
def aliased_table_for(table_name, aliased_name, type_caster)
|
63
52
|
if aliases[table_name].zero?
|
64
53
|
# If it's zero, we can have our table_name
|
65
54
|
aliases[table_name] = 1
|
66
|
-
Arel::Table.new(table_name, type_caster:
|
55
|
+
Arel::Table.new(table_name, type_caster: type_caster)
|
67
56
|
else
|
68
57
|
# Otherwise, we need to use an alias
|
69
58
|
aliased_name = @connection.table_alias_for(aliased_name)
|
@@ -76,10 +65,12 @@ module ActiveRecord
|
|
76
65
|
else
|
77
66
|
aliased_name
|
78
67
|
end
|
79
|
-
Arel::Table.new(table_name, type_caster:
|
68
|
+
Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
|
80
69
|
end
|
81
70
|
end
|
82
71
|
|
72
|
+
attr_reader :aliases
|
73
|
+
|
83
74
|
private
|
84
75
|
|
85
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
|
@@ -30,14 +32,6 @@ module ActiveRecord
|
|
30
32
|
reset_scope
|
31
33
|
end
|
32
34
|
|
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
35
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
36
|
def reset
|
43
37
|
@loaded = false
|
@@ -94,7 +88,7 @@ module ActiveRecord
|
|
94
88
|
# actually gets built.
|
95
89
|
def association_scope
|
96
90
|
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self
|
91
|
+
@association_scope ||= AssociationScope.scope(self)
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
@@ -130,7 +124,17 @@ module ActiveRecord
|
|
130
124
|
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
131
125
|
# through association's scope)
|
132
126
|
def target_scope
|
133
|
-
AssociationRelation.create(klass,
|
127
|
+
AssociationRelation.create(klass, self).merge!(klass.all)
|
128
|
+
end
|
129
|
+
|
130
|
+
def extensions
|
131
|
+
extensions = klass.default_extensions | reflection.extensions
|
132
|
+
|
133
|
+
if reflection.scope
|
134
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
135
|
+
end
|
136
|
+
|
137
|
+
extensions
|
134
138
|
end
|
135
139
|
|
136
140
|
# Loads the \target if needed and returns it.
|
@@ -152,14 +156,6 @@ module ActiveRecord
|
|
152
156
|
reset
|
153
157
|
end
|
154
158
|
|
155
|
-
def interpolate(sql, record = nil)
|
156
|
-
if sql.respond_to?(:to_proc)
|
157
|
-
owner.instance_exec(record, &sql)
|
158
|
-
else
|
159
|
-
sql
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
159
|
# We can't dump @reflection since it contains the scope proc
|
164
160
|
def marshal_dump
|
165
161
|
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
@@ -177,8 +173,8 @@ module ActiveRecord
|
|
177
173
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
178
174
|
assigned_keys = record.changed_attribute_names_to_save
|
179
175
|
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
180
|
-
attributes =
|
181
|
-
record.
|
176
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
177
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
182
178
|
set_inverse_instance(record)
|
183
179
|
end
|
184
180
|
|
@@ -191,6 +187,9 @@ module ActiveRecord
|
|
191
187
|
end
|
192
188
|
|
193
189
|
private
|
190
|
+
def scope_for_create
|
191
|
+
scope.scope_for_create
|
192
|
+
end
|
194
193
|
|
195
194
|
def find_target?
|
196
195
|
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
@@ -274,7 +273,7 @@ module ActiveRecord
|
|
274
273
|
end
|
275
274
|
|
276
275
|
# Returns true if statement cache should be skipped on the association reader.
|
277
|
-
def skip_statement_cache?
|
276
|
+
def skip_statement_cache?(scope)
|
278
277
|
reflection.has_scope? ||
|
279
278
|
scope.eager_loading? ||
|
280
279
|
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
|
-
|
27
|
-
scope.extending! Array(reflection.options[:extend])
|
28
|
-
add_constraints(scope, owner, reflection, chain_head, chain_tail)
|
29
|
-
end
|
26
|
+
chain = get_chain(reflection, association, scope.alias_tracker)
|
30
27
|
|
31
|
-
|
32
|
-
|
28
|
+
scope.extending! reflection.extensions
|
29
|
+
add_constraints(scope, owner, chain)
|
33
30
|
end
|
34
31
|
|
35
32
|
def self.get_bind_values(owner, chain)
|
@@ -57,20 +54,21 @@ 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
|
-
scope = scope
|
67
|
+
scope = apply_scope(scope, table, key, value)
|
70
68
|
|
71
69
|
if reflection.type
|
72
70
|
polymorphic_type = transform_value(owner.class.base_class.name)
|
73
|
-
scope = scope
|
71
|
+
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
74
72
|
end
|
75
73
|
|
76
74
|
scope
|
@@ -80,28 +78,29 @@ 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
91
|
value = transform_value(next_reflection.klass.base_class.name)
|
92
|
-
scope = scope
|
92
|
+
scope = apply_scope(scope, table, reflection.type, value)
|
93
93
|
end
|
94
94
|
|
95
|
-
scope
|
95
|
+
scope.joins!(join(foreign_table, constraint))
|
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,38 +108,33 @@ 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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
113
|
+
aliased_table = tracker.aliased_table_for(
|
114
|
+
refl.table_name,
|
115
|
+
refl.alias_candidate(name),
|
116
|
+
refl.klass.type_caster
|
117
|
+
)
|
118
|
+
chain << ReflectionProxy.new(refl, aliased_table)
|
119
119
|
end
|
120
|
-
|
120
|
+
chain
|
121
121
|
end
|
122
122
|
|
123
|
-
def add_constraints(scope, owner,
|
124
|
-
|
125
|
-
table = owner_reflection.alias_name
|
126
|
-
scope = last_chain_scope(scope, table, owner_reflection, owner)
|
123
|
+
def add_constraints(scope, owner, chain)
|
124
|
+
scope = last_chain_scope(scope, chain.last, owner)
|
127
125
|
|
128
|
-
reflection
|
129
|
-
|
130
|
-
|
131
|
-
next_reflection = reflection.next
|
132
|
-
|
133
|
-
unless reflection == chain_tail
|
134
|
-
foreign_table = next_reflection.alias_name
|
135
|
-
scope = next_chain_scope(scope, table, reflection, foreign_table, next_reflection)
|
136
|
-
end
|
126
|
+
chain.each_cons(2) do |reflection, next_reflection|
|
127
|
+
scope = next_chain_scope(scope, reflection, next_reflection)
|
128
|
+
end
|
137
129
|
|
130
|
+
chain_head = chain.first
|
131
|
+
chain.reverse_each do |reflection|
|
138
132
|
# Exclude the scope of the association itself, because that
|
139
133
|
# was already merged in the #scope method.
|
140
134
|
reflection.constraints.each do |scope_chain_item|
|
141
|
-
item = eval_scope(reflection
|
135
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
142
136
|
|
143
|
-
if scope_chain_item ==
|
137
|
+
if scope_chain_item == chain_head.scope
|
144
138
|
scope.merge! item.except(:where, :includes)
|
145
139
|
end
|
146
140
|
|
@@ -152,16 +146,22 @@ module ActiveRecord
|
|
152
146
|
scope.where_clause += item.where_clause
|
153
147
|
scope.order_values |= item.order_values
|
154
148
|
end
|
155
|
-
|
156
|
-
reflection = next_reflection
|
157
149
|
end
|
158
150
|
|
159
151
|
scope
|
160
152
|
end
|
161
153
|
|
162
|
-
def
|
163
|
-
|
164
|
-
|
154
|
+
def apply_scope(scope, table, key, value)
|
155
|
+
if scope.table == table
|
156
|
+
scope.where!(key => value)
|
157
|
+
else
|
158
|
+
scope.where!(table.name => { key => value })
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def eval_scope(reflection, scope, owner)
|
163
|
+
relation = reflection.build_scope(reflection.aliased_table)
|
164
|
+
relation.instance_exec(owner, &scope) || relation
|
165
165
|
end
|
166
166
|
end
|
167
167
|
end
|
@@ -1,6 +1,8 @@
|
|
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
|
target.send(options[:dependent]) if load_target
|
@@ -10,17 +12,20 @@ module ActiveRecord
|
|
10
12
|
if record
|
11
13
|
raise_on_type_mismatch!(record)
|
12
14
|
update_counters_on_replace(record)
|
13
|
-
replace_keys(record)
|
14
15
|
set_inverse_instance(record)
|
15
16
|
@updated = true
|
16
17
|
else
|
17
18
|
decrement_counters
|
18
|
-
remove_keys
|
19
19
|
end
|
20
20
|
|
21
21
|
self.target = record
|
22
22
|
end
|
23
23
|
|
24
|
+
def target=(record)
|
25
|
+
replace_keys(record)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
24
29
|
def default(&block)
|
25
30
|
writer(owner.instance_exec(&block)) if reader.nil?
|
26
31
|
end
|
@@ -47,9 +52,9 @@ module ActiveRecord
|
|
47
52
|
def update_counters(by)
|
48
53
|
if require_counter_update? && foreign_key_present?
|
49
54
|
if target && !stale_target?
|
50
|
-
target.increment!(reflection.counter_cache_column, by)
|
55
|
+
target.increment!(reflection.counter_cache_column, by, touch: reflection.options[:touch])
|
51
56
|
else
|
52
|
-
klass.update_counters(target_id, reflection.counter_cache_column => by)
|
57
|
+
klass.update_counters(target_id, reflection.counter_cache_column => by, touch: reflection.options[:touch])
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -76,11 +81,8 @@ module ActiveRecord
|
|
76
81
|
end
|
77
82
|
|
78
83
|
def replace_keys(record)
|
79
|
-
owner[reflection.foreign_key] = record
|
80
|
-
|
81
|
-
|
82
|
-
def remove_keys
|
83
|
-
owner[reflection.foreign_key] = nil
|
84
|
+
owner[reflection.foreign_key] = record ?
|
85
|
+
record._read_attribute(reflection.association_primary_key(record.class)) : nil
|
84
86
|
end
|
85
87
|
|
86
88
|
def foreign_key_present?
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Belongs To Polymorphic Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Belongs To Polymorphic Association
|
4
6
|
class BelongsToPolymorphicAssociation < BelongsToAssociation #:nodoc:
|
5
7
|
def klass
|
6
8
|
type = owner[reflection.foreign_type]
|
@@ -11,12 +13,7 @@ module ActiveRecord
|
|
11
13
|
|
12
14
|
def replace_keys(record)
|
13
15
|
super
|
14
|
-
owner[reflection.foreign_type] = record.class.base_class.name
|
15
|
-
end
|
16
|
-
|
17
|
-
def remove_keys
|
18
|
-
super
|
19
|
-
owner[reflection.foreign_type] = nil
|
16
|
+
owner[reflection.foreign_type] = record ? record.class.base_class.name : nil
|
20
17
|
end
|
21
18
|
|
22
19
|
def different_target?(record)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This is the parent Association class which defines the variables
|
2
4
|
# used by all associations.
|
3
5
|
#
|
@@ -36,11 +38,6 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
36
38
|
def self.create_reflection(model, name, scope, options, extension = nil)
|
37
39
|
raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)
|
38
40
|
|
39
|
-
if scope.is_a?(Hash)
|
40
|
-
options = scope
|
41
|
-
scope = nil
|
42
|
-
end
|
43
|
-
|
44
41
|
validate_options(options)
|
45
42
|
|
46
43
|
scope = build_scope(scope, extension)
|
@@ -107,8 +104,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
107
104
|
|
108
105
|
def self.define_readers(mixin, name)
|
109
106
|
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
110
|
-
def #{name}
|
111
|
-
association(:#{name}).reader
|
107
|
+
def #{name}
|
108
|
+
association(:#{name}).reader
|
112
109
|
end
|
113
110
|
CODE
|
114
111
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord::Associations::Builder # :nodoc:
|
2
4
|
class BelongsTo < SingularAssociation #:nodoc:
|
3
5
|
def self.macro
|
@@ -32,9 +34,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
32
34
|
foreign_key = reflection.foreign_key
|
33
35
|
cache_column = reflection.counter_cache_column
|
34
36
|
|
35
|
-
if (@
|
36
|
-
@_after_create_counter_called = false
|
37
|
-
elsif (@_after_replace_counter_called ||= false)
|
37
|
+
if (@_after_replace_counter_called ||= false)
|
38
38
|
@_after_replace_counter_called = false
|
39
39
|
elsif saved_change_to_attribute?(foreign_key) && !new_record?
|
40
40
|
if reflection.polymorphic?
|
@@ -114,9 +114,13 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
114
114
|
BelongsTo.touch_record(record, record.send(changes_method), foreign_key, n, touch, belongs_to_touch_method)
|
115
115
|
}}
|
116
116
|
|
117
|
-
|
118
|
-
|
119
|
-
|
117
|
+
unless reflection.counter_cache_column
|
118
|
+
model.after_create callback.(:saved_changes), if: :saved_changes?
|
119
|
+
model.after_destroy callback.(:changes_to_save)
|
120
|
+
end
|
121
|
+
|
122
|
+
model.after_update callback.(:saved_changes), if: :saved_changes?
|
123
|
+
model.after_touch callback.(:changes_to_save)
|
120
124
|
end
|
121
125
|
|
122
126
|
def self.add_default_callbacks(model, reflection)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord::Associations::Builder # :nodoc:
|
2
4
|
class HasAndBelongsToMany # :nodoc:
|
3
5
|
class JoinTableResolver # :nodoc:
|
@@ -45,7 +47,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
45
47
|
habtm = JoinTableResolver.build lhs_model, association_name, options
|
46
48
|
|
47
49
|
join_model = Class.new(ActiveRecord::Base) {
|
48
|
-
class << self
|
50
|
+
class << self
|
49
51
|
attr_accessor :left_model
|
50
52
|
attr_accessor :name
|
51
53
|
attr_accessor :table_name_resolver
|