activerecord 5.1.7 → 5.2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +556 -685
- 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 +40 -63
- 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.rb +48 -93
- 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/preloader.rb +18 -38
- 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/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- 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 +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/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 +2 -0
- 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.rb +3 -1
- 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 +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/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 +41 -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.rb +189 -139
- 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/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 +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 +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation.rb +120 -214
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- 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.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 +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/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 +9 -8
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -7
- 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.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 +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_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 +35 -5
- 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 +23 -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 -122
- data/lib/active_record/attribute_set.rb +0 -113
- 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/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
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Query Cache
|
3
5
|
class QueryCache
|
@@ -24,16 +26,12 @@ module ActiveRecord
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def self.run
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
caching_pool.enable_query_cache!
|
31
|
-
|
32
|
-
[caching_pool, caching_was_enabled]
|
29
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.
|
30
|
+
reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
|
33
31
|
end
|
34
32
|
|
35
|
-
def self.complete(
|
36
|
-
|
33
|
+
def self.complete(pools)
|
34
|
+
pools.each { |pool| pool.disable_query_cache! }
|
37
35
|
|
38
36
|
ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
|
39
37
|
pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Querying
|
3
5
|
delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
|
@@ -5,7 +7,7 @@ module ActiveRecord
|
|
5
7
|
delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
|
6
8
|
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
7
9
|
delegate :find_by, :find_by!, to: :all
|
8
|
-
delegate :
|
10
|
+
delegate :destroy_all, :delete_all, :update_all, to: :all
|
9
11
|
delegate :find_each, :find_in_batches, :in_batches, to: :all
|
10
12
|
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
|
11
13
|
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
|
@@ -38,7 +40,7 @@ module ActiveRecord
|
|
38
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
39
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
40
42
|
column_types = result_set.column_types.dup
|
41
|
-
|
43
|
+
attribute_types.each_key { |k| column_types.delete k }
|
42
44
|
message_bus = ActiveSupport::Notifications.instrumenter
|
43
45
|
|
44
46
|
payload = {
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record"
|
2
4
|
require "rails"
|
3
5
|
require "active_model/railtie"
|
@@ -26,6 +28,9 @@ module ActiveRecord
|
|
26
28
|
config.active_record.use_schema_cache_dump = true
|
27
29
|
config.active_record.maintain_test_schema = true
|
28
30
|
|
31
|
+
config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
|
32
|
+
config.active_record.sqlite3.represent_boolean_as_integer = nil
|
33
|
+
|
29
34
|
config.eager_load_namespaces << ActiveRecord
|
30
35
|
|
31
36
|
rake_tasks do
|
@@ -54,6 +59,7 @@ module ActiveRecord
|
|
54
59
|
console = ActiveSupport::Logger.new(STDERR)
|
55
60
|
Rails.logger.extend ActiveSupport::Logger.broadcast console
|
56
61
|
end
|
62
|
+
ActiveRecord::Base.verbose_query_logs = false
|
57
63
|
end
|
58
64
|
|
59
65
|
runner do
|
@@ -85,12 +91,16 @@ module ActiveRecord
|
|
85
91
|
filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
|
86
92
|
|
87
93
|
if File.file?(filename)
|
94
|
+
current_version = ActiveRecord::Migrator.current_version
|
95
|
+
|
96
|
+
next if current_version.nil?
|
97
|
+
|
88
98
|
cache = YAML.load(File.read(filename))
|
89
|
-
if cache.version ==
|
99
|
+
if cache.version == current_version
|
90
100
|
connection.schema_cache = cache
|
91
101
|
connection_pool.schema_cache = cache.dup
|
92
102
|
else
|
93
|
-
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{
|
103
|
+
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|
@@ -108,7 +118,9 @@ module ActiveRecord
|
|
108
118
|
|
109
119
|
initializer "active_record.set_configs" do |app|
|
110
120
|
ActiveSupport.on_load(:active_record) do
|
111
|
-
app.config.active_record.
|
121
|
+
configs = app.config.active_record.dup
|
122
|
+
configs.delete(:sqlite3)
|
123
|
+
configs.each do |k, v|
|
112
124
|
send "#{k}=", v
|
113
125
|
end
|
114
126
|
end
|
@@ -157,14 +169,58 @@ end_warning
|
|
157
169
|
end
|
158
170
|
|
159
171
|
initializer "active_record.set_executor_hooks" do
|
160
|
-
|
161
|
-
ActiveRecord::QueryCache.install_executor_hooks
|
162
|
-
end
|
172
|
+
ActiveRecord::QueryCache.install_executor_hooks
|
163
173
|
end
|
164
174
|
|
165
175
|
initializer "active_record.add_watchable_files" do |app|
|
166
176
|
path = app.paths["db"].first
|
167
177
|
config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
|
168
178
|
end
|
179
|
+
|
180
|
+
initializer "active_record.clear_active_connections" do
|
181
|
+
config.after_initialize do
|
182
|
+
ActiveSupport.on_load(:active_record) do
|
183
|
+
# Ideally the application doesn't connect to the database during boot,
|
184
|
+
# but sometimes it does. In case it did, we want to empty out the
|
185
|
+
# connection pools so that a non-database-using process (e.g. a master
|
186
|
+
# process in a forking server model) doesn't retain a needless
|
187
|
+
# connection. If it was needed, the incremental cost of reestablishing
|
188
|
+
# this connection is trivial: the rest of the pool would need to be
|
189
|
+
# populated anyway.
|
190
|
+
|
191
|
+
clear_active_connections!
|
192
|
+
flush_idle_connections!
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
|
198
|
+
config.after_initialize do
|
199
|
+
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
200
|
+
represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
|
201
|
+
unless represent_boolean_as_integer.nil?
|
202
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
|
203
|
+
end
|
204
|
+
|
205
|
+
unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
206
|
+
ActiveSupport::Deprecation.warn <<-MSG
|
207
|
+
Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
208
|
+
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
|
209
|
+
boolean values and must have old data converted to 1 and 0 (its native boolean
|
210
|
+
serialization) before setting this flag to true. Conversion can be accomplished
|
211
|
+
by setting up a rake task which runs
|
212
|
+
|
213
|
+
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
214
|
+
ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
|
215
|
+
|
216
|
+
for all models and all boolean columns, after which the flag must be set to
|
217
|
+
true by adding the following to your application.rb file:
|
218
|
+
|
219
|
+
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
|
220
|
+
MSG
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
169
225
|
end
|
170
226
|
end
|
@@ -1,17 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record"
|
2
4
|
|
3
5
|
db_namespace = namespace :db do
|
4
6
|
desc "Set the environment value for the database"
|
5
|
-
task "environment:set" =>
|
7
|
+
task "environment:set" => :load_config do
|
6
8
|
ActiveRecord::InternalMetadata.create_table
|
7
|
-
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::
|
9
|
+
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
|
8
10
|
end
|
9
11
|
|
10
|
-
task check_protected_environments:
|
12
|
+
task check_protected_environments: :load_config do
|
11
13
|
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
|
12
14
|
end
|
13
15
|
|
14
|
-
task :
|
16
|
+
task load_config: :environment do
|
15
17
|
ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
|
16
18
|
ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
|
17
19
|
end
|
@@ -54,7 +56,7 @@ db_namespace = namespace :db do
|
|
54
56
|
end
|
55
57
|
|
56
58
|
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
57
|
-
task migrate:
|
59
|
+
task migrate: :load_config do
|
58
60
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
59
61
|
db_namespace["_dump"].invoke
|
60
62
|
end
|
@@ -76,7 +78,7 @@ db_namespace = namespace :db do
|
|
76
78
|
|
77
79
|
namespace :migrate do
|
78
80
|
# desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
|
79
|
-
task redo:
|
81
|
+
task redo: :load_config do
|
80
82
|
raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
|
81
83
|
|
82
84
|
if ENV["VERSION"]
|
@@ -92,24 +94,33 @@ db_namespace = namespace :db do
|
|
92
94
|
task reset: ["db:drop", "db:create", "db:migrate"]
|
93
95
|
|
94
96
|
# desc 'Runs the "up" for a given migration VERSION.'
|
95
|
-
task up:
|
97
|
+
task up: :load_config do
|
96
98
|
raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
+
ActiveRecord::Tasks::DatabaseTasks.check_target_version
|
101
|
+
|
102
|
+
ActiveRecord::Base.connection.migration_context.run(
|
103
|
+
:up,
|
104
|
+
ActiveRecord::Tasks::DatabaseTasks.target_version
|
105
|
+
)
|
100
106
|
db_namespace["_dump"].invoke
|
101
107
|
end
|
102
108
|
|
103
109
|
# desc 'Runs the "down" for a given migration VERSION.'
|
104
|
-
task down:
|
110
|
+
task down: :load_config do
|
105
111
|
raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty?
|
106
|
-
|
107
|
-
ActiveRecord::
|
112
|
+
|
113
|
+
ActiveRecord::Tasks::DatabaseTasks.check_target_version
|
114
|
+
|
115
|
+
ActiveRecord::Base.connection.migration_context.run(
|
116
|
+
:down,
|
117
|
+
ActiveRecord::Tasks::DatabaseTasks.target_version
|
118
|
+
)
|
108
119
|
db_namespace["_dump"].invoke
|
109
120
|
end
|
110
121
|
|
111
122
|
desc "Display status of migrations"
|
112
|
-
task status:
|
123
|
+
task status: :load_config do
|
113
124
|
unless ActiveRecord::SchemaMigration.table_exists?
|
114
125
|
abort "Schema migrations table does not exist yet."
|
115
126
|
end
|
@@ -118,8 +129,7 @@ db_namespace = namespace :db do
|
|
118
129
|
puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
|
119
130
|
puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
|
120
131
|
puts "-" * 50
|
121
|
-
|
122
|
-
ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
|
132
|
+
ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
|
123
133
|
puts "#{status.center(8)} #{version.ljust(14)} #{name}"
|
124
134
|
end
|
125
135
|
puts
|
@@ -127,16 +137,16 @@ db_namespace = namespace :db do
|
|
127
137
|
end
|
128
138
|
|
129
139
|
desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
|
130
|
-
task rollback:
|
140
|
+
task rollback: :load_config do
|
131
141
|
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
|
132
|
-
ActiveRecord::
|
142
|
+
ActiveRecord::Base.connection.migration_context.rollback(step)
|
133
143
|
db_namespace["_dump"].invoke
|
134
144
|
end
|
135
145
|
|
136
146
|
# desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
|
137
|
-
task forward:
|
147
|
+
task forward: :load_config do
|
138
148
|
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
|
139
|
-
ActiveRecord::
|
149
|
+
ActiveRecord::Base.connection.migration_context.forward(step)
|
140
150
|
db_namespace["_dump"].invoke
|
141
151
|
end
|
142
152
|
|
@@ -144,12 +154,12 @@ db_namespace = namespace :db do
|
|
144
154
|
task reset: [ "db:drop", "db:setup" ]
|
145
155
|
|
146
156
|
# desc "Retrieves the charset for the current environment's database"
|
147
|
-
task charset:
|
157
|
+
task charset: :load_config do
|
148
158
|
puts ActiveRecord::Tasks::DatabaseTasks.charset_current
|
149
159
|
end
|
150
160
|
|
151
161
|
# desc "Retrieves the collation for the current environment's database"
|
152
|
-
task collation:
|
162
|
+
task collation: :load_config do
|
153
163
|
begin
|
154
164
|
puts ActiveRecord::Tasks::DatabaseTasks.collation_current
|
155
165
|
rescue NoMethodError
|
@@ -158,13 +168,13 @@ db_namespace = namespace :db do
|
|
158
168
|
end
|
159
169
|
|
160
170
|
desc "Retrieves the current schema version number"
|
161
|
-
task version:
|
162
|
-
puts "Current version: #{ActiveRecord::
|
171
|
+
task version: :load_config do
|
172
|
+
puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
|
163
173
|
end
|
164
174
|
|
165
175
|
# desc "Raises an error if there are pending migrations"
|
166
|
-
task abort_if_pending_migrations:
|
167
|
-
pending_migrations = ActiveRecord::
|
176
|
+
task abort_if_pending_migrations: :load_config do
|
177
|
+
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
|
168
178
|
|
169
179
|
if pending_migrations.any?
|
170
180
|
puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
|
@@ -186,7 +196,7 @@ db_namespace = namespace :db do
|
|
186
196
|
|
187
197
|
namespace :fixtures do
|
188
198
|
desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
|
189
|
-
task load:
|
199
|
+
task load: :load_config do
|
190
200
|
require "active_record/fixtures"
|
191
201
|
|
192
202
|
base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
|
@@ -208,7 +218,7 @@ db_namespace = namespace :db do
|
|
208
218
|
end
|
209
219
|
|
210
220
|
# desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
|
211
|
-
task identify:
|
221
|
+
task identify: :load_config do
|
212
222
|
require "active_record/fixtures"
|
213
223
|
|
214
224
|
label, id = ENV["LABEL"], ENV["ID"]
|
@@ -219,7 +229,7 @@ db_namespace = namespace :db do
|
|
219
229
|
base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
|
220
230
|
|
221
231
|
Dir["#{base_dir}/**/*.yml"].each do |file|
|
222
|
-
if data = YAML
|
232
|
+
if data = YAML.load(ERB.new(IO.read(file)).result)
|
223
233
|
data.each_key do |key|
|
224
234
|
key_id = ActiveRecord::FixtureSet.identify(key)
|
225
235
|
|
@@ -234,7 +244,7 @@ db_namespace = namespace :db do
|
|
234
244
|
|
235
245
|
namespace :schema do
|
236
246
|
desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
|
237
|
-
task dump:
|
247
|
+
task dump: :load_config do
|
238
248
|
require "active_record/schema_dumper"
|
239
249
|
filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
|
240
250
|
File.open(filename, "w:utf-8") do |file|
|
@@ -244,7 +254,7 @@ db_namespace = namespace :db do
|
|
244
254
|
end
|
245
255
|
|
246
256
|
desc "Loads a schema.rb file into the database"
|
247
|
-
task load: [:
|
257
|
+
task load: [:load_config, :check_protected_environments] do
|
248
258
|
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV["SCHEMA"])
|
249
259
|
end
|
250
260
|
|
@@ -254,14 +264,14 @@ db_namespace = namespace :db do
|
|
254
264
|
|
255
265
|
namespace :cache do
|
256
266
|
desc "Creates a db/schema_cache.yml file."
|
257
|
-
task dump:
|
267
|
+
task dump: :load_config do
|
258
268
|
conn = ActiveRecord::Base.connection
|
259
269
|
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
|
260
270
|
ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
|
261
271
|
end
|
262
272
|
|
263
273
|
desc "Clears a db/schema_cache.yml file."
|
264
|
-
task clear:
|
274
|
+
task clear: :load_config do
|
265
275
|
filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
|
266
276
|
rm_f filename, verbose: false
|
267
277
|
end
|
@@ -271,7 +281,7 @@ db_namespace = namespace :db do
|
|
271
281
|
|
272
282
|
namespace :structure do
|
273
283
|
desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
|
274
|
-
task dump:
|
284
|
+
task dump: :load_config do
|
275
285
|
filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
|
276
286
|
current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
|
277
287
|
ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
|
@@ -286,7 +296,7 @@ db_namespace = namespace :db do
|
|
286
296
|
end
|
287
297
|
|
288
298
|
desc "Recreates the databases from the structure.sql file"
|
289
|
-
task load: [:
|
299
|
+
task load: [:load_config, :check_protected_environments] do
|
290
300
|
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV["SCHEMA"])
|
291
301
|
end
|
292
302
|
|
@@ -325,12 +335,12 @@ db_namespace = namespace :db do
|
|
325
335
|
end
|
326
336
|
|
327
337
|
# desc "Empty the test database"
|
328
|
-
task purge: %w(
|
338
|
+
task purge: %w(load_config check_protected_environments) do
|
329
339
|
ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
|
330
340
|
end
|
331
341
|
|
332
342
|
# desc 'Load the test schema'
|
333
|
-
task prepare:
|
343
|
+
task prepare: :load_config do
|
334
344
|
unless ActiveRecord::Base.configurations.blank?
|
335
345
|
db_namespace["test:load"].invoke
|
336
346
|
end
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ReadonlyAttributes
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
class_attribute :_attr_readonly, instance_accessor: false
|
7
|
-
self._attr_readonly = []
|
8
|
+
class_attribute :_attr_readonly, instance_accessor: false, default: []
|
8
9
|
end
|
9
10
|
|
10
11
|
module ClassMethods
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "active_support/core_ext/string/filters"
|
3
|
-
require "
|
4
|
+
require "concurrent/map"
|
4
5
|
|
5
6
|
module ActiveRecord
|
6
7
|
# = Active Record Reflection
|
@@ -8,10 +9,8 @@ module ActiveRecord
|
|
8
9
|
extend ActiveSupport::Concern
|
9
10
|
|
10
11
|
included do
|
11
|
-
class_attribute :_reflections, instance_writer: false
|
12
|
-
class_attribute :aggregate_reflections, instance_writer: false
|
13
|
-
self._reflections = {}
|
14
|
-
self.aggregate_reflections = {}
|
12
|
+
class_attribute :_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.create(macro, name, scope, options, ar)
|
@@ -139,7 +138,7 @@ module ActiveRecord
|
|
139
138
|
# HasAndBelongsToManyReflection
|
140
139
|
# ThroughReflection
|
141
140
|
# PolymorphicReflection
|
142
|
-
#
|
141
|
+
# RuntimeReflection
|
143
142
|
class AbstractReflection # :nodoc:
|
144
143
|
def through_reflection?
|
145
144
|
false
|
@@ -155,14 +154,6 @@ module ActiveRecord
|
|
155
154
|
klass.new(attributes, &block)
|
156
155
|
end
|
157
156
|
|
158
|
-
def quoted_table_name
|
159
|
-
klass.quoted_table_name
|
160
|
-
end
|
161
|
-
|
162
|
-
def primary_key_type
|
163
|
-
klass.type_for_attribute(klass.primary_key)
|
164
|
-
end
|
165
|
-
|
166
157
|
# Returns the class name for the macro.
|
167
158
|
#
|
168
159
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
@@ -174,7 +165,7 @@ module ActiveRecord
|
|
174
165
|
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
175
166
|
|
176
167
|
def join_keys
|
177
|
-
get_join_keys
|
168
|
+
@join_keys ||= get_join_keys(klass)
|
178
169
|
end
|
179
170
|
|
180
171
|
# Returns a list of scopes that should be applied for this Reflection
|
@@ -183,22 +174,30 @@ module ActiveRecord
|
|
183
174
|
scope ? [scope] : []
|
184
175
|
end
|
185
176
|
|
186
|
-
def
|
187
|
-
chain.map(&:scopes)
|
188
|
-
end
|
189
|
-
deprecate :scope_chain
|
190
|
-
|
191
|
-
def join_scope(table)
|
177
|
+
def join_scope(table, foreign_table, foreign_klass)
|
192
178
|
predicate_builder = predicate_builder(table)
|
193
179
|
scope_chain_items = join_scopes(table, predicate_builder)
|
194
180
|
klass_scope = klass_join_scope(table, predicate_builder)
|
195
181
|
|
196
|
-
|
182
|
+
key = join_keys.key
|
183
|
+
foreign_key = join_keys.foreign_key
|
184
|
+
|
185
|
+
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
186
|
+
|
187
|
+
if type
|
188
|
+
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
189
|
+
end
|
190
|
+
|
191
|
+
if klass.finder_needs_type_condition?
|
192
|
+
klass_scope.where!(klass.send(:type_condition, table))
|
193
|
+
end
|
194
|
+
|
195
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
197
196
|
end
|
198
197
|
|
199
198
|
def join_scopes(table, predicate_builder) # :nodoc:
|
200
199
|
if scope
|
201
|
-
[build_scope(table, predicate_builder)
|
200
|
+
[scope_for(build_scope(table, predicate_builder))]
|
202
201
|
else
|
203
202
|
[]
|
204
203
|
end
|
@@ -210,7 +209,7 @@ module ActiveRecord
|
|
210
209
|
end
|
211
210
|
|
212
211
|
def constraints
|
213
|
-
chain.
|
212
|
+
chain.flat_map(&:scopes)
|
214
213
|
end
|
215
214
|
|
216
215
|
def counter_cache_column
|
@@ -284,24 +283,37 @@ module ActiveRecord
|
|
284
283
|
end
|
285
284
|
|
286
285
|
def get_join_keys(association_klass)
|
287
|
-
JoinKeys.new(
|
286
|
+
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
288
287
|
end
|
289
288
|
|
290
289
|
def build_scope(table, predicate_builder = predicate_builder(table))
|
291
|
-
Relation.create(
|
290
|
+
Relation.create(
|
291
|
+
klass,
|
292
|
+
table: table,
|
293
|
+
predicate_builder: predicate_builder
|
294
|
+
)
|
295
|
+
end
|
296
|
+
|
297
|
+
def join_primary_key(*)
|
298
|
+
foreign_key
|
299
|
+
end
|
300
|
+
|
301
|
+
def join_foreign_key
|
302
|
+
active_record_primary_key
|
292
303
|
end
|
293
304
|
|
305
|
+
protected
|
306
|
+
def actual_source_reflection # FIXME: this is a horrible name
|
307
|
+
self
|
308
|
+
end
|
309
|
+
|
294
310
|
private
|
295
311
|
def predicate_builder(table)
|
296
312
|
PredicateBuilder.new(TableMetadata.new(klass, table))
|
297
313
|
end
|
298
314
|
|
299
|
-
def
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
def join_fk
|
304
|
-
active_record_primary_key
|
315
|
+
def primary_key(klass)
|
316
|
+
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
305
317
|
end
|
306
318
|
end
|
307
319
|
|
@@ -348,6 +360,17 @@ module ActiveRecord
|
|
348
360
|
#
|
349
361
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
|
350
362
|
# <tt>has_many :clients</tt> returns the Client class
|
363
|
+
#
|
364
|
+
# class Company < ActiveRecord::Base
|
365
|
+
# has_many :clients
|
366
|
+
# end
|
367
|
+
#
|
368
|
+
# Company.reflect_on_association(:clients).klass
|
369
|
+
# # => Client
|
370
|
+
#
|
371
|
+
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
372
|
+
# a new association object. Use +build_association+ or +create_association+
|
373
|
+
# instead. This allows plugins to hook into association object creation.
|
351
374
|
def klass
|
352
375
|
@klass ||= compute_class(class_name)
|
353
376
|
end
|
@@ -366,8 +389,8 @@ module ActiveRecord
|
|
366
389
|
active_record == other_aggregation.active_record
|
367
390
|
end
|
368
391
|
|
369
|
-
def scope_for(
|
370
|
-
|
392
|
+
def scope_for(relation, owner = nil)
|
393
|
+
relation.instance_exec(owner, &scope) || relation
|
371
394
|
end
|
372
395
|
|
373
396
|
private
|
@@ -388,23 +411,10 @@ module ActiveRecord
|
|
388
411
|
# Holds all the metadata about an association as it was specified in the
|
389
412
|
# Active Record class.
|
390
413
|
class AssociationReflection < MacroReflection #:nodoc:
|
391
|
-
# Returns the target association's class.
|
392
|
-
#
|
393
|
-
# class Author < ActiveRecord::Base
|
394
|
-
# has_many :books
|
395
|
-
# end
|
396
|
-
#
|
397
|
-
# Author.reflect_on_association(:books).klass
|
398
|
-
# # => Book
|
399
|
-
#
|
400
|
-
# <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
|
401
|
-
# a new association object. Use +build_association+ or +create_association+
|
402
|
-
# instead. This allows plugins to hook into association object creation.
|
403
|
-
def klass
|
404
|
-
@klass ||= compute_class(class_name)
|
405
|
-
end
|
406
|
-
|
407
414
|
def compute_class(name)
|
415
|
+
if polymorphic?
|
416
|
+
raise ArgumentError, "Polymorphic association does not support to compute class."
|
417
|
+
end
|
408
418
|
active_record.send(:compute_type, name)
|
409
419
|
end
|
410
420
|
|
@@ -414,31 +424,21 @@ module ActiveRecord
|
|
414
424
|
def initialize(name, scope, options, active_record)
|
415
425
|
super
|
416
426
|
@type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
|
417
|
-
@foreign_type = options[:foreign_type] || "#{name}_type"
|
427
|
+
@foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
|
418
428
|
@constructable = calculate_constructable(macro, options)
|
419
|
-
@association_scope_cache =
|
420
|
-
@scope_lock = Mutex.new
|
429
|
+
@association_scope_cache = Concurrent::Map.new
|
421
430
|
|
422
431
|
if options[:class_name] && options[:class_name].class == Class
|
423
|
-
|
424
|
-
Passing a class to the `class_name` is deprecated and will raise
|
425
|
-
an ArgumentError in Rails 5.2. It eagerloads more classes than
|
426
|
-
necessary and potentially creates circular dependencies.
|
427
|
-
|
428
|
-
Please pass the class name as a string:
|
429
|
-
`#{macro} :#{name}, class_name: '#{options[:class_name]}'`
|
430
|
-
MSG
|
432
|
+
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
431
433
|
end
|
432
434
|
end
|
433
435
|
|
434
|
-
def association_scope_cache(conn, owner)
|
436
|
+
def association_scope_cache(conn, owner, &block)
|
435
437
|
key = conn.prepared_statements
|
436
438
|
if polymorphic?
|
437
439
|
key = [key, owner._read_attribute(@foreign_type)]
|
438
440
|
end
|
439
|
-
@association_scope_cache
|
440
|
-
@association_scope_cache[key] ||= yield
|
441
|
-
}
|
441
|
+
@association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
|
442
442
|
end
|
443
443
|
|
444
444
|
def constructable? # :nodoc:
|
@@ -462,10 +462,6 @@ module ActiveRecord
|
|
462
462
|
options[:primary_key] || primary_key(klass || self.klass)
|
463
463
|
end
|
464
464
|
|
465
|
-
def association_primary_key_type
|
466
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
467
|
-
end
|
468
|
-
|
469
465
|
def active_record_primary_key
|
470
466
|
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
471
467
|
end
|
@@ -488,7 +484,7 @@ module ActiveRecord
|
|
488
484
|
alias :check_eager_loadable! :check_preloadable!
|
489
485
|
|
490
486
|
def join_id_for(owner) # :nodoc:
|
491
|
-
owner[
|
487
|
+
owner[join_foreign_key]
|
492
488
|
end
|
493
489
|
|
494
490
|
def through_reflection
|
@@ -571,7 +567,7 @@ module ActiveRecord
|
|
571
567
|
end
|
572
568
|
|
573
569
|
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
574
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:
|
570
|
+
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
575
571
|
|
576
572
|
def add_as_source(seed)
|
577
573
|
seed
|
@@ -589,12 +585,6 @@ module ActiveRecord
|
|
589
585
|
Array(options[:extend])
|
590
586
|
end
|
591
587
|
|
592
|
-
protected
|
593
|
-
|
594
|
-
def actual_source_reflection # FIXME: this is a horrible name
|
595
|
-
self
|
596
|
-
end
|
597
|
-
|
598
588
|
private
|
599
589
|
|
600
590
|
def calculate_constructable(macro, options)
|
@@ -635,12 +625,9 @@ module ActiveRecord
|
|
635
625
|
# +automatic_inverse_of+ method is a valid reflection. We must
|
636
626
|
# make sure that the reflection's active_record name matches up
|
637
627
|
# with the current reflection's klass name.
|
638
|
-
#
|
639
|
-
# Note: klass will always be valid because when there's a NameError
|
640
|
-
# from calling +klass+, +reflection+ will already be set to false.
|
641
628
|
def valid_inverse_reflection?(reflection)
|
642
629
|
reflection &&
|
643
|
-
klass
|
630
|
+
klass <= reflection.active_record &&
|
644
631
|
can_find_inverse_of_automatically?(reflection)
|
645
632
|
end
|
646
633
|
|
@@ -648,9 +635,8 @@ module ActiveRecord
|
|
648
635
|
# us from being able to guess the inverse automatically. First, the
|
649
636
|
# <tt>inverse_of</tt> option cannot be set to false. Second, we must
|
650
637
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
651
|
-
# Third, we must not have options such as <tt>:
|
652
|
-
#
|
653
|
-
# inverse association.
|
638
|
+
# Third, we must not have options such as <tt>:foreign_key</tt>
|
639
|
+
# which prevent us from correctly guessing the inverse association.
|
654
640
|
#
|
655
641
|
# Anything with a scope can additionally ruin our attempt at finding an
|
656
642
|
# inverse, so we exclude reflections with scopes.
|
@@ -680,10 +666,6 @@ module ActiveRecord
|
|
680
666
|
def derive_join_table
|
681
667
|
ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
|
682
668
|
end
|
683
|
-
|
684
|
-
def primary_key(klass)
|
685
|
-
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
686
|
-
end
|
687
669
|
end
|
688
670
|
|
689
671
|
class HasManyReflection < AssociationReflection # :nodoc:
|
@@ -737,30 +719,25 @@ module ActiveRecord
|
|
737
719
|
end
|
738
720
|
end
|
739
721
|
|
740
|
-
def
|
741
|
-
|
722
|
+
def join_primary_key(klass = nil)
|
723
|
+
polymorphic? ? association_primary_key(klass) : association_primary_key
|
724
|
+
end
|
725
|
+
|
726
|
+
def join_foreign_key
|
727
|
+
foreign_key
|
742
728
|
end
|
743
729
|
|
744
730
|
private
|
731
|
+
def can_find_inverse_of_automatically?(_)
|
732
|
+
!polymorphic? && super
|
733
|
+
end
|
745
734
|
|
746
735
|
def calculate_constructable(macro, options)
|
747
736
|
!polymorphic?
|
748
737
|
end
|
749
|
-
|
750
|
-
def join_fk
|
751
|
-
foreign_key
|
752
|
-
end
|
753
|
-
|
754
|
-
def join_pk(klass)
|
755
|
-
polymorphic? ? association_primary_key(klass) : association_primary_key
|
756
|
-
end
|
757
738
|
end
|
758
739
|
|
759
740
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
760
|
-
def initialize(name, scope, options, active_record)
|
761
|
-
super
|
762
|
-
end
|
763
|
-
|
764
741
|
def macro; :has_and_belongs_to_many; end
|
765
742
|
|
766
743
|
def collection?
|
@@ -771,8 +748,7 @@ module ActiveRecord
|
|
771
748
|
# Holds all the metadata about a :through association as it was specified
|
772
749
|
# in the Active Record class.
|
773
750
|
class ThroughReflection < AbstractReflection #:nodoc:
|
774
|
-
|
775
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key,
|
751
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
776
752
|
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
|
777
753
|
|
778
754
|
def initialize(delegate_reflection)
|
@@ -863,10 +839,6 @@ module ActiveRecord
|
|
863
839
|
source_reflection.join_scopes(table, predicate_builder) + super
|
864
840
|
end
|
865
841
|
|
866
|
-
def source_type_scope
|
867
|
-
through_reflection.klass.where(foreign_type => options[:source_type])
|
868
|
-
end
|
869
|
-
|
870
842
|
def has_scope?
|
871
843
|
scope || options[:source_type] ||
|
872
844
|
source_reflection.has_scope? ||
|
@@ -887,10 +859,6 @@ module ActiveRecord
|
|
887
859
|
actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
|
888
860
|
end
|
889
861
|
|
890
|
-
def association_primary_key_type
|
891
|
-
klass.type_for_attribute(association_primary_key.to_s)
|
892
|
-
end
|
893
|
-
|
894
862
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
895
863
|
#
|
896
864
|
# class Post < ActiveRecord::Base
|
@@ -935,10 +903,6 @@ module ActiveRecord
|
|
935
903
|
through_reflection.options
|
936
904
|
end
|
937
905
|
|
938
|
-
def join_id_for(owner) # :nodoc:
|
939
|
-
source_reflection.join_id_for(owner)
|
940
|
-
end
|
941
|
-
|
942
906
|
def check_validity!
|
943
907
|
if through_reflection.nil?
|
944
908
|
raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
|
@@ -997,23 +961,23 @@ module ActiveRecord
|
|
997
961
|
collect_join_reflections(seed + [self])
|
998
962
|
end
|
999
963
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
else
|
1005
|
-
through_reflection.add_as_through a
|
1006
|
-
end
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
private
|
964
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
965
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
966
|
+
protected
|
967
|
+
attr_reader :delegate_reflection
|
1010
968
|
|
1011
969
|
def actual_source_reflection # FIXME: this is a horrible name
|
1012
|
-
source_reflection.
|
970
|
+
source_reflection.actual_source_reflection
|
1013
971
|
end
|
1014
972
|
|
1015
|
-
|
1016
|
-
|
973
|
+
private
|
974
|
+
def collect_join_reflections(seed)
|
975
|
+
a = source_reflection.add_as_source seed
|
976
|
+
if options[:source_type]
|
977
|
+
through_reflection.add_as_polymorphic_through self, a
|
978
|
+
else
|
979
|
+
through_reflection.add_as_through a
|
980
|
+
end
|
1017
981
|
end
|
1018
982
|
|
1019
983
|
def inverse_name; delegate_reflection.send(:inverse_name); end
|
@@ -1030,66 +994,32 @@ module ActiveRecord
|
|
1030
994
|
end
|
1031
995
|
|
1032
996
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
997
|
+
delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
|
998
|
+
|
1033
999
|
def initialize(reflection, previous_reflection)
|
1034
1000
|
@reflection = reflection
|
1035
1001
|
@previous_reflection = previous_reflection
|
1036
1002
|
end
|
1037
1003
|
|
1038
|
-
def scopes
|
1039
|
-
scopes = @previous_reflection.scopes
|
1040
|
-
if @previous_reflection.options[:source_type]
|
1041
|
-
scopes + [@previous_reflection.source_type_scope]
|
1042
|
-
else
|
1043
|
-
scopes
|
1044
|
-
end
|
1045
|
-
end
|
1046
|
-
|
1047
1004
|
def join_scopes(table, predicate_builder) # :nodoc:
|
1048
1005
|
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1049
|
-
|
1050
|
-
scopes + [@previous_reflection.source_type_scope]
|
1051
|
-
else
|
1052
|
-
scopes
|
1053
|
-
end
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
def klass
|
1057
|
-
@reflection.klass
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
def scope
|
1061
|
-
@reflection.scope
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
def table_name
|
1065
|
-
@reflection.table_name
|
1066
|
-
end
|
1067
|
-
|
1068
|
-
def plural_name
|
1069
|
-
@reflection.plural_name
|
1070
|
-
end
|
1071
|
-
|
1072
|
-
def type
|
1073
|
-
@reflection.type
|
1006
|
+
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1074
1007
|
end
|
1075
1008
|
|
1076
1009
|
def constraints
|
1077
|
-
@reflection.constraints + [
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
def source_type_info
|
1081
|
-
type = @previous_reflection.foreign_type
|
1082
|
-
source_type = @previous_reflection.options[:source_type]
|
1083
|
-
lambda { |object| where(type => source_type) }
|
1010
|
+
@reflection.constraints + [source_type_scope]
|
1084
1011
|
end
|
1085
1012
|
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1013
|
+
private
|
1014
|
+
def source_type_scope
|
1015
|
+
type = @previous_reflection.foreign_type
|
1016
|
+
source_type = @previous_reflection.options[:source_type]
|
1017
|
+
lambda { |object| where(type => source_type) }
|
1018
|
+
end
|
1089
1019
|
end
|
1090
1020
|
|
1091
|
-
class RuntimeReflection <
|
1092
|
-
|
1021
|
+
class RuntimeReflection < AbstractReflection # :nodoc:
|
1022
|
+
delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
|
1093
1023
|
|
1094
1024
|
def initialize(reflection, association)
|
1095
1025
|
@reflection = reflection
|
@@ -1100,24 +1030,8 @@ module ActiveRecord
|
|
1100
1030
|
@association.klass
|
1101
1031
|
end
|
1102
1032
|
|
1103
|
-
def
|
1104
|
-
klass.
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
def constraints
|
1108
|
-
@reflection.constraints
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
def source_type_info
|
1112
|
-
@reflection.source_type_info
|
1113
|
-
end
|
1114
|
-
|
1115
|
-
def alias_candidate(name)
|
1116
|
-
"#{plural_name}_#{name}_join"
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
def alias_name
|
1120
|
-
Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1033
|
+
def aliased_table
|
1034
|
+
@aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
|
1121
1035
|
end
|
1122
1036
|
|
1123
1037
|
def all_includes; yield; end
|