activerecord 5.1.0 → 5.2.3
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 +596 -450
- 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.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +77 -85
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +49 -35
- data/lib/active_record/associations/association_scope.rb +55 -55
- data/lib/active_record/associations/belongs_to_association.rb +30 -11
- 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 +21 -8
- 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 +66 -53
- data/lib/active_record/associations/collection_proxy.rb +30 -73
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +13 -2
- data/lib/active_record/associations/has_many_through_association.rb +37 -19
- data/lib/active_record/associations/has_one_association.rb +14 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +52 -96
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
- 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/preloader.rb +17 -37
- 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/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +27 -12
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +33 -216
- 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 +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 +22 -19
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +15 -13
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -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 +15 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
- 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 +65 -7
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
- 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 +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -15
- 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.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- 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 +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 +8 -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/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 +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 +258 -129
- 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 +75 -87
- 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 +24 -1
- 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 +90 -96
- 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 +41 -61
- data/lib/active_record/counter_cache.rb +20 -15
- 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 +60 -15
- 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 +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 +30 -42
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +81 -29
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +74 -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 +199 -54
- data/lib/active_record/query_cache.rb +8 -10
- data/lib/active_record/querying.rb +5 -3
- data/lib/active_record/railtie.rb +62 -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 +48 -38
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +137 -207
- data/lib/active_record/relation.rb +132 -207
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +66 -25
- data/lib/active_record/relation/delegation.rb +45 -29
- data/lib/active_record/relation/finder_methods.rb +76 -85
- 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.rb +60 -79
- 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/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +135 -103
- 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 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- 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.rb +12 -10
- data/lib/active_record/scoping/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +40 -12
- 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 +38 -26
- 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 +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- 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 +6 -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_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.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 +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- 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.rb +2 -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/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
- metadata +24 -36
- 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.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -113
- data/lib/active_record/attribute_set.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/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
@@ -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,14 +57,18 @@ 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)
|
48
67
|
if require_counter_update? && foreign_key_present?
|
49
68
|
if target && !stale_target?
|
50
|
-
target.increment!(reflection.counter_cache_column, by)
|
69
|
+
target.increment!(reflection.counter_cache_column, by, touch: reflection.options[:touch])
|
51
70
|
else
|
52
|
-
klass.update_counters(target_id, reflection.counter_cache_column => by)
|
71
|
+
klass.update_counters(target_id, reflection.counter_cache_column => by, touch: reflection.options[:touch])
|
53
72
|
end
|
54
73
|
end
|
55
74
|
end
|
@@ -65,22 +84,22 @@ module ActiveRecord
|
|
65
84
|
def update_counters_on_replace(record)
|
66
85
|
if require_counter_update? && different_target?(record)
|
67
86
|
owner.instance_variable_set :@_after_replace_counter_called, true
|
68
|
-
record.increment!(reflection.counter_cache_column)
|
87
|
+
record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch])
|
69
88
|
decrement_counters
|
70
89
|
end
|
71
90
|
end
|
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?
|
@@ -1,22 +1,22 @@
|
|
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]
|
7
9
|
type.presence && type.constantize
|
8
10
|
end
|
9
11
|
|
10
|
-
|
12
|
+
def target_changed?
|
13
|
+
super || owner.saved_change_to_attribute?(reflection.foreign_type)
|
14
|
+
end
|
11
15
|
|
16
|
+
private
|
12
17
|
def replace_keys(record)
|
13
18
|
super
|
14
|
-
owner[reflection.foreign_type] = record.class.
|
15
|
-
end
|
16
|
-
|
17
|
-
def remove_keys
|
18
|
-
super
|
19
|
-
owner[reflection.foreign_type] = nil
|
19
|
+
owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
|
20
20
|
end
|
21
21
|
|
22
22
|
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,11 +34,9 @@ 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
|
-
elsif
|
39
|
+
elsif association(reflection.name).target_changed?
|
40
40
|
if reflection.polymorphic?
|
41
41
|
model = attribute_in_database(reflection.foreign_type).try(:constantize)
|
42
42
|
model_was = attribute_before_last_save(reflection.foreign_type).try(:constantize)
|
@@ -49,14 +49,22 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
49
49
|
foreign_key = attribute_in_database foreign_key
|
50
50
|
|
51
51
|
if foreign_key && model.respond_to?(:increment_counter)
|
52
|
+
foreign_key = counter_cache_target(reflection, model, foreign_key)
|
52
53
|
model.increment_counter(cache_column, foreign_key)
|
53
54
|
end
|
54
55
|
|
55
56
|
if foreign_key_was && model_was.respond_to?(:decrement_counter)
|
57
|
+
foreign_key_was = counter_cache_target(reflection, model_was, foreign_key_was)
|
56
58
|
model_was.decrement_counter(cache_column, foreign_key_was)
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def counter_cache_target(reflection, model, foreign_key)
|
65
|
+
primary_key = reflection.association_primary_key(model)
|
66
|
+
model.unscoped.where!(primary_key => foreign_key)
|
67
|
+
end
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
@@ -84,7 +92,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
84
92
|
else
|
85
93
|
klass = association.klass
|
86
94
|
end
|
87
|
-
|
95
|
+
primary_key = reflection.association_primary_key(klass)
|
96
|
+
old_record = klass.find_by(primary_key => old_foreign_id)
|
88
97
|
|
89
98
|
if old_record
|
90
99
|
if touch != true
|
@@ -114,9 +123,13 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
114
123
|
BelongsTo.touch_record(record, record.send(changes_method), foreign_key, n, touch, belongs_to_touch_method)
|
115
124
|
}}
|
116
125
|
|
117
|
-
|
118
|
-
|
119
|
-
|
126
|
+
unless reflection.counter_cache_column
|
127
|
+
model.after_create callback.(:saved_changes), if: :saved_changes?
|
128
|
+
model.after_destroy callback.(:changes_to_save)
|
129
|
+
end
|
130
|
+
|
131
|
+
model.after_update callback.(:saved_changes), if: :saved_changes?
|
132
|
+
model.after_touch callback.(:changes_to_save)
|
120
133
|
end
|
121
134
|
|
122
135
|
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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
# = Active Record Association Collection
|
@@ -30,7 +32,8 @@ module ActiveRecord
|
|
30
32
|
reload
|
31
33
|
end
|
32
34
|
|
33
|
-
CollectionProxy.create(klass, self)
|
35
|
+
@proxy ||= CollectionProxy.create(klass, self)
|
36
|
+
@proxy.reset_scope
|
34
37
|
end
|
35
38
|
|
36
39
|
# Implements the writer method, e.g. foo.items= for Foo.has_many :items
|
@@ -42,24 +45,28 @@ module ActiveRecord
|
|
42
45
|
def ids_reader
|
43
46
|
if loaded?
|
44
47
|
target.pluck(reflection.association_primary_key)
|
48
|
+
elsif !target.empty?
|
49
|
+
load_target.pluck(reflection.association_primary_key)
|
45
50
|
else
|
46
|
-
@association_ids ||= (
|
47
|
-
column = "#{reflection.quoted_table_name}.#{reflection.association_primary_key}"
|
48
|
-
scope.pluck(column)
|
49
|
-
)
|
51
|
+
@association_ids ||= scope.pluck(reflection.association_primary_key)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
# Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
|
54
56
|
def ids_writer(ids)
|
55
|
-
|
57
|
+
primary_key = reflection.association_primary_key
|
58
|
+
pk_type = klass.type_for_attribute(primary_key)
|
56
59
|
ids = Array(ids).reject(&:blank?)
|
57
60
|
ids.map! { |i| pk_type.cast(i) }
|
58
|
-
|
59
|
-
|
61
|
+
|
62
|
+
records = klass.where(primary_key => ids).index_by do |r|
|
63
|
+
r.public_send(primary_key)
|
60
64
|
end.values_at(*ids).compact
|
65
|
+
|
61
66
|
if records.size != ids.size
|
62
|
-
|
67
|
+
found_ids = records.map { |record| record.public_send(primary_key) }
|
68
|
+
not_found_ids = ids - found_ids
|
69
|
+
klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key, not_found_ids)
|
63
70
|
else
|
64
71
|
replace(records)
|
65
72
|
end
|
@@ -68,26 +75,29 @@ module ActiveRecord
|
|
68
75
|
def reset
|
69
76
|
super
|
70
77
|
@target = []
|
78
|
+
@association_ids = nil
|
71
79
|
end
|
72
80
|
|
73
81
|
def find(*args)
|
74
|
-
if
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
if options[:inverse_of] && loaded?
|
83
|
+
args_flatten = args.flatten
|
84
|
+
model = scope.klass
|
85
|
+
|
86
|
+
if args_flatten.blank?
|
87
|
+
error_message = "Couldn't find #{model.name} without an ID"
|
88
|
+
raise RecordNotFound.new(error_message, model.name, model.primary_key, args)
|
89
|
+
end
|
90
|
+
|
91
|
+
result = find_by_scan(*args)
|
92
|
+
|
93
|
+
result_size = Array(result).size
|
94
|
+
if !result || result_size != args_flatten.size
|
95
|
+
scope.raise_record_not_found_exception!(args_flatten, result_size, args_flatten.size)
|
88
96
|
else
|
89
|
-
|
97
|
+
result
|
90
98
|
end
|
99
|
+
else
|
100
|
+
scope.find(*args)
|
91
101
|
end
|
92
102
|
end
|
93
103
|
|
@@ -95,15 +105,12 @@ module ActiveRecord
|
|
95
105
|
if attributes.is_a?(Array)
|
96
106
|
attributes.collect { |attr| build(attr, &block) }
|
97
107
|
else
|
98
|
-
add_to_target(build_record(attributes))
|
99
|
-
yield(record) if block_given?
|
100
|
-
end
|
108
|
+
add_to_target(build_record(attributes, &block))
|
101
109
|
end
|
102
110
|
end
|
103
111
|
|
104
|
-
# Add +records+ to this association.
|
105
|
-
#
|
106
|
-
# +push+ and +concat+ behave identically.
|
112
|
+
# Add +records+ to this association. Since +<<+ flattens its argument list
|
113
|
+
# and inserts each record, +push+ and +concat+ behave identically.
|
107
114
|
def concat(*records)
|
108
115
|
records = records.flatten
|
109
116
|
if owner.new_record?
|
@@ -179,8 +186,6 @@ module ActiveRecord
|
|
179
186
|
# are actually removed from the database, that depends precisely on
|
180
187
|
# +delete_records+. They are in any case removed from the collection.
|
181
188
|
def delete(*records)
|
182
|
-
return if records.empty?
|
183
|
-
records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
|
184
189
|
delete_or_destroy(records, options[:dependent])
|
185
190
|
end
|
186
191
|
|
@@ -190,8 +195,6 @@ module ActiveRecord
|
|
190
195
|
# Note that this method removes records from the database ignoring the
|
191
196
|
# +:dependent+ option.
|
192
197
|
def destroy(*records)
|
193
|
-
return if records.empty?
|
194
|
-
records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
|
195
198
|
delete_or_destroy(records, :destroy)
|
196
199
|
end
|
197
200
|
|
@@ -299,18 +302,17 @@ module ActiveRecord
|
|
299
302
|
private
|
300
303
|
|
301
304
|
def find_target
|
302
|
-
|
305
|
+
scope = self.scope
|
306
|
+
return scope.to_a if skip_statement_cache?(scope)
|
303
307
|
|
304
308
|
conn = klass.connection
|
305
|
-
sc = reflection.association_scope_cache(conn, owner) do
|
306
|
-
|
307
|
-
|
308
|
-
target_scope.merge as.scope(self, conn)
|
309
|
-
}
|
309
|
+
sc = reflection.association_scope_cache(conn, owner) do |params|
|
310
|
+
as = AssociationScope.create { params.bind }
|
311
|
+
target_scope.merge!(as.scope(self))
|
310
312
|
end
|
311
313
|
|
312
314
|
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
313
|
-
sc.execute(binds,
|
315
|
+
sc.execute(binds, conn) do |record|
|
314
316
|
set_inverse_instance(record)
|
315
317
|
end
|
316
318
|
end
|
@@ -353,12 +355,17 @@ module ActiveRecord
|
|
353
355
|
if attributes.is_a?(Array)
|
354
356
|
attributes.collect { |attr| _create_record(attr, raise, &block) }
|
355
357
|
else
|
358
|
+
record = build_record(attributes, &block)
|
356
359
|
transaction do
|
357
|
-
|
358
|
-
|
359
|
-
insert_record(record, true, raise) {
|
360
|
+
result = nil
|
361
|
+
add_to_target(record) do
|
362
|
+
result = insert_record(record, true, raise) {
|
363
|
+
@_was_loaded = loaded?
|
364
|
+
}
|
360
365
|
end
|
366
|
+
raise ActiveRecord::Rollback unless result
|
361
367
|
end
|
368
|
+
record
|
362
369
|
end
|
363
370
|
end
|
364
371
|
|
@@ -371,11 +378,9 @@ module ActiveRecord
|
|
371
378
|
end
|
372
379
|
end
|
373
380
|
|
374
|
-
def create_scope
|
375
|
-
scope.scope_for_create.stringify_keys
|
376
|
-
end
|
377
|
-
|
378
381
|
def delete_or_destroy(records, method)
|
382
|
+
return if records.empty?
|
383
|
+
records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
|
379
384
|
records = records.flatten
|
380
385
|
records.each { |record| raise_on_type_mismatch!(record) }
|
381
386
|
existing_records = records.reject(&:new_record?)
|
@@ -392,6 +397,7 @@ module ActiveRecord
|
|
392
397
|
|
393
398
|
delete_records(existing_records, method) if existing_records.any?
|
394
399
|
records.each { |record| target.delete(record) }
|
400
|
+
@association_ids = nil
|
395
401
|
|
396
402
|
records.each { |record| callback(:after_remove, record) }
|
397
403
|
end
|
@@ -404,9 +410,9 @@ module ActiveRecord
|
|
404
410
|
end
|
405
411
|
|
406
412
|
def replace_records(new_target, original_target)
|
407
|
-
delete(target
|
413
|
+
delete(difference(target, new_target))
|
408
414
|
|
409
|
-
unless concat(new_target
|
415
|
+
unless concat(difference(new_target, target))
|
410
416
|
@target = original_target
|
411
417
|
raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
|
412
418
|
"new records could not be saved."
|
@@ -416,7 +422,7 @@ module ActiveRecord
|
|
416
422
|
end
|
417
423
|
|
418
424
|
def replace_common_records_in_memory(new_target, original_target)
|
419
|
-
common_records = new_target
|
425
|
+
common_records = intersection(new_target, original_target)
|
420
426
|
common_records.each do |record|
|
421
427
|
skip_callbacks = true
|
422
428
|
replace_on_target(record, @target.index(record), skip_callbacks)
|
@@ -429,11 +435,17 @@ module ActiveRecord
|
|
429
435
|
records.each do |record|
|
430
436
|
raise_on_type_mismatch!(record)
|
431
437
|
add_to_target(record) do
|
432
|
-
|
438
|
+
unless owner.new_record?
|
439
|
+
result &&= insert_record(record, true, raise) {
|
440
|
+
@_was_loaded = loaded?
|
441
|
+
}
|
442
|
+
end
|
433
443
|
end
|
434
444
|
end
|
435
445
|
|
436
|
-
|
446
|
+
raise ActiveRecord::Rollback unless result
|
447
|
+
|
448
|
+
records
|
437
449
|
end
|
438
450
|
|
439
451
|
def replace_on_target(record, index, skip_callbacks)
|
@@ -448,6 +460,7 @@ module ActiveRecord
|
|
448
460
|
if index
|
449
461
|
target[index] = record
|
450
462
|
elsif @_was_loaded || !loaded?
|
463
|
+
@association_ids = nil
|
451
464
|
target << record
|
452
465
|
end
|
453
466
|
|