activerecord 5.2.6 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +609 -622
- data/MIT-LICENSE +3 -1
- data/README.rdoc +4 -2
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations/association.rb +52 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +3 -13
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +6 -21
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -10
- data/lib/active_record/associations/has_many_through_association.rb +14 -14
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +24 -28
- data/lib/active_record/associations/preloader/association.rb +38 -36
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/preloader.rb +40 -32
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations.rb +19 -14
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -22
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -53
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +17 -24
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attributes.rb +13 -0
- data/lib/active_record/autosave_association.rb +5 -9
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +5 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +94 -16
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +95 -123
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
- data/lib/active_record/connection_adapters/abstract_adapter.rb +180 -47
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +128 -194
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +73 -13
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +160 -74
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +125 -141
- data/lib/active_record/connection_handling.rb +149 -27
- data/lib/active_record/core.rb +100 -60
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/enum.rb +37 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +145 -472
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -3
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +10 -2
- data/lib/active_record/locking/optimistic.rb +5 -6
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +50 -6
- data/lib/active_record/migration/compatibility.rb +76 -49
- data/lib/active_record/migration.rb +100 -81
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +228 -24
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +32 -20
- data/lib/active_record/railtie.rb +80 -43
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +196 -46
- data/lib/active_record/reflection.rb +32 -30
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +53 -47
- data/lib/active_record/relation/delegation.rb +26 -43
- data/lib/active_record/relation/finder_methods.rb +13 -26
- data/lib/active_record/relation/merger.rb +11 -20
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +189 -63
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +14 -10
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +310 -80
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +5 -1
- data/lib/active_record/scoping/default.rb +4 -5
- data/lib/active_record/scoping/named.rb +19 -15
- data/lib/active_record/scoping.rb +8 -8
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/table_metadata.rb +10 -17
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +4 -2
- data/lib/active_record/transactions.rb +57 -66
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +9 -2
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +108 -26
- data/lib/active_record/collection_cache_key.rb +0 -53
data/lib/active_record/core.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/hash/indifferent_access"
|
4
4
|
require "active_support/core_ext/string/filters"
|
5
|
+
require "active_support/parameter_filter"
|
5
6
|
require "concurrent/map"
|
6
7
|
|
7
8
|
module ActiveRecord
|
@@ -26,7 +27,7 @@ module ActiveRecord
|
|
26
27
|
|
27
28
|
##
|
28
29
|
# Contains the database configuration - as is typically stored in config/database.yml -
|
29
|
-
# as
|
30
|
+
# as an ActiveRecord::DatabaseConfigurations object.
|
30
31
|
#
|
31
32
|
# For example, the following database.yml...
|
32
33
|
#
|
@@ -40,22 +41,18 @@ module ActiveRecord
|
|
40
41
|
#
|
41
42
|
# ...would result in ActiveRecord::Base.configurations to look like this:
|
42
43
|
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# 'adapter' => 'sqlite3',
|
50
|
-
# 'database' => 'db/production.sqlite3'
|
51
|
-
# }
|
52
|
-
# }
|
44
|
+
# #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
|
45
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
46
|
+
# @spec_name="primary", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}>,
|
47
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
|
48
|
+
# @spec_name="primary", @config={"adapter"=>"mysql2", "database"=>"db/production.sqlite3"}>
|
49
|
+
# ]>
|
53
50
|
def self.configurations=(config)
|
54
|
-
@@configurations = ActiveRecord::
|
51
|
+
@@configurations = ActiveRecord::DatabaseConfigurations.new(config)
|
55
52
|
end
|
56
53
|
self.configurations = {}
|
57
54
|
|
58
|
-
# Returns fully resolved
|
55
|
+
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
59
56
|
def self.configurations
|
60
57
|
@@configurations
|
61
58
|
end
|
@@ -99,7 +96,7 @@ module ActiveRecord
|
|
99
96
|
##
|
100
97
|
# :singleton-method:
|
101
98
|
# Specify whether schema dump should happen at the end of the
|
102
|
-
# db:migrate
|
99
|
+
# db:migrate rails command. This is true by default, which is useful for the
|
103
100
|
# development environment. This should ideally be false in the production
|
104
101
|
# environment where dumping schema is rarely needed.
|
105
102
|
mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
|
@@ -125,25 +122,28 @@ module ActiveRecord
|
|
125
122
|
|
126
123
|
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
127
124
|
|
125
|
+
mattr_accessor :connection_handlers, instance_accessor: false, default: {}
|
126
|
+
|
127
|
+
mattr_accessor :writing_role, instance_accessor: false, default: :writing
|
128
|
+
|
129
|
+
mattr_accessor :reading_role, instance_accessor: false, default: :reading
|
130
|
+
|
128
131
|
class_attribute :default_connection_handler, instance_writer: false
|
129
132
|
|
133
|
+
self.filter_attributes = []
|
134
|
+
|
130
135
|
def self.connection_handler
|
131
|
-
|
136
|
+
Thread.current.thread_variable_get("ar_connection_handler") || default_connection_handler
|
132
137
|
end
|
133
138
|
|
134
139
|
def self.connection_handler=(handler)
|
135
|
-
|
140
|
+
Thread.current.thread_variable_set("ar_connection_handler", handler)
|
136
141
|
end
|
137
142
|
|
138
143
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
139
144
|
end
|
140
145
|
|
141
|
-
module ClassMethods
|
142
|
-
def allocate
|
143
|
-
define_attribute_methods
|
144
|
-
super
|
145
|
-
end
|
146
|
-
|
146
|
+
module ClassMethods
|
147
147
|
def initialize_find_by_cache # :nodoc:
|
148
148
|
@find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
|
149
149
|
end
|
@@ -160,7 +160,7 @@ module ActiveRecord
|
|
160
160
|
return super if block_given? ||
|
161
161
|
primary_key.nil? ||
|
162
162
|
scope_attributes? ||
|
163
|
-
columns_hash.
|
163
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
164
164
|
|
165
165
|
id = ids.first
|
166
166
|
|
@@ -172,20 +172,16 @@ module ActiveRecord
|
|
172
172
|
where(key => params.bind).limit(1)
|
173
173
|
}
|
174
174
|
|
175
|
-
record = statement.execute([id], connection)
|
175
|
+
record = statement.execute([id], connection)&.first
|
176
176
|
unless record
|
177
|
-
raise RecordNotFound.new("Couldn't find #{name} with '#{
|
178
|
-
name, primary_key, id)
|
177
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{key}'=#{id}", name, key, id)
|
179
178
|
end
|
180
179
|
record
|
181
|
-
rescue ::RangeError
|
182
|
-
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
183
|
-
name, primary_key)
|
184
180
|
end
|
185
181
|
|
186
182
|
def find_by(*args) # :nodoc:
|
187
183
|
return super if scope_attributes? || reflect_on_all_aggregations.any? ||
|
188
|
-
columns_hash.key?(inheritance_column) && base_class
|
184
|
+
columns_hash.key?(inheritance_column) && !base_class?
|
189
185
|
|
190
186
|
hash = args.first
|
191
187
|
|
@@ -205,11 +201,9 @@ module ActiveRecord
|
|
205
201
|
where(wheres).limit(1)
|
206
202
|
}
|
207
203
|
begin
|
208
|
-
statement.execute(hash.values, connection)
|
204
|
+
statement.execute(hash.values, connection)&.first
|
209
205
|
rescue TypeError
|
210
206
|
raise ActiveRecord::StatementInvalid
|
211
|
-
rescue ::RangeError
|
212
|
-
nil
|
213
207
|
end
|
214
208
|
end
|
215
209
|
|
@@ -221,7 +215,7 @@ module ActiveRecord
|
|
221
215
|
generated_association_methods
|
222
216
|
end
|
223
217
|
|
224
|
-
def generated_association_methods
|
218
|
+
def generated_association_methods # :nodoc:
|
225
219
|
@generated_association_methods ||= begin
|
226
220
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
227
221
|
private_constant :GeneratedAssociationMethods
|
@@ -231,8 +225,20 @@ module ActiveRecord
|
|
231
225
|
end
|
232
226
|
end
|
233
227
|
|
228
|
+
# Returns columns which shouldn't be exposed while calling +#inspect+.
|
229
|
+
def filter_attributes
|
230
|
+
if defined?(@filter_attributes)
|
231
|
+
@filter_attributes
|
232
|
+
else
|
233
|
+
superclass.filter_attributes
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Specifies columns which shouldn't be exposed while calling +#inspect+.
|
238
|
+
attr_writer :filter_attributes
|
239
|
+
|
234
240
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
235
|
-
def inspect
|
241
|
+
def inspect # :nodoc:
|
236
242
|
if self == Base
|
237
243
|
super
|
238
244
|
elsif abstract_class?
|
@@ -248,7 +254,7 @@ module ActiveRecord
|
|
248
254
|
end
|
249
255
|
|
250
256
|
# Overwrite the default class equality method to provide support for decorated models.
|
251
|
-
def ===(object)
|
257
|
+
def ===(object) # :nodoc:
|
252
258
|
object.is_a?(self)
|
253
259
|
end
|
254
260
|
|
@@ -262,7 +268,8 @@ module ActiveRecord
|
|
262
268
|
end
|
263
269
|
|
264
270
|
def arel_attribute(name, table = arel_table) # :nodoc:
|
265
|
-
name =
|
271
|
+
name = name.to_s
|
272
|
+
name = attribute_aliases[name] || name
|
266
273
|
table[name]
|
267
274
|
end
|
268
275
|
|
@@ -274,6 +281,10 @@ module ActiveRecord
|
|
274
281
|
TypeCaster::Map.new(self)
|
275
282
|
end
|
276
283
|
|
284
|
+
def _internal? # :nodoc:
|
285
|
+
false
|
286
|
+
end
|
287
|
+
|
277
288
|
private
|
278
289
|
|
279
290
|
def cached_find_by_statement(key, &block)
|
@@ -306,7 +317,7 @@ module ActiveRecord
|
|
306
317
|
# # Instantiates a single new object
|
307
318
|
# User.new(first_name: 'Jamie')
|
308
319
|
def initialize(attributes = nil)
|
309
|
-
|
320
|
+
@new_record = true
|
310
321
|
@attributes = self.class._default_attributes.deep_dup
|
311
322
|
|
312
323
|
init_internals
|
@@ -332,15 +343,21 @@ module ActiveRecord
|
|
332
343
|
# post = Post.allocate
|
333
344
|
# post.init_with(coder)
|
334
345
|
# post.title # => 'hello world'
|
335
|
-
def init_with(coder)
|
346
|
+
def init_with(coder, &block)
|
336
347
|
coder = LegacyYamlAdapter.convert(self.class, coder)
|
337
|
-
|
338
|
-
|
339
|
-
|
348
|
+
attributes = self.class.yaml_encoder.decode(coder)
|
349
|
+
init_with_attributes(attributes, coder["new_record"], &block)
|
350
|
+
end
|
340
351
|
|
341
|
-
|
352
|
+
##
|
353
|
+
# Initialize an empty model object from +attributes+.
|
354
|
+
# +attributes+ should be an attributes object, and unlike the
|
355
|
+
# `initialize` method, no assignment calls are made per attribute.
|
356
|
+
def init_with_attributes(attributes, new_record = false) # :nodoc:
|
357
|
+
@new_record = new_record
|
358
|
+
@attributes = attributes
|
342
359
|
|
343
|
-
|
360
|
+
init_internals
|
344
361
|
|
345
362
|
yield self if block_given?
|
346
363
|
|
@@ -379,13 +396,13 @@ module ActiveRecord
|
|
379
396
|
##
|
380
397
|
def initialize_dup(other) # :nodoc:
|
381
398
|
@attributes = @attributes.deep_dup
|
382
|
-
@attributes.reset(
|
399
|
+
@attributes.reset(@primary_key)
|
383
400
|
|
384
401
|
_run_initialize_callbacks
|
385
402
|
|
386
403
|
@new_record = true
|
387
404
|
@destroyed = false
|
388
|
-
@_start_transaction_state =
|
405
|
+
@_start_transaction_state = nil
|
389
406
|
@transaction_state = nil
|
390
407
|
|
391
408
|
super
|
@@ -446,6 +463,7 @@ module ActiveRecord
|
|
446
463
|
|
447
464
|
# Returns +true+ if the attributes hash has been frozen.
|
448
465
|
def frozen?
|
466
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
449
467
|
@attributes.frozen?
|
450
468
|
end
|
451
469
|
|
@@ -458,6 +476,14 @@ module ActiveRecord
|
|
458
476
|
end
|
459
477
|
end
|
460
478
|
|
479
|
+
def present? # :nodoc:
|
480
|
+
true
|
481
|
+
end
|
482
|
+
|
483
|
+
def blank? # :nodoc:
|
484
|
+
false
|
485
|
+
end
|
486
|
+
|
461
487
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
462
488
|
# attributes will be marked as read only since they cannot be saved.
|
463
489
|
def readonly?
|
@@ -480,7 +506,14 @@ module ActiveRecord
|
|
480
506
|
inspection = if defined?(@attributes) && @attributes
|
481
507
|
self.class.attribute_names.collect do |name|
|
482
508
|
if has_attribute?(name)
|
483
|
-
|
509
|
+
attr = _read_attribute(name)
|
510
|
+
value = if attr.nil?
|
511
|
+
attr.inspect
|
512
|
+
else
|
513
|
+
attr = format_for_inspect(attr)
|
514
|
+
inspection_filter.filter_param(name, attr)
|
515
|
+
end
|
516
|
+
"#{name}: #{value}"
|
484
517
|
end
|
485
518
|
end.compact.join(", ")
|
486
519
|
else
|
@@ -496,15 +529,16 @@ module ActiveRecord
|
|
496
529
|
return super if custom_inspect_method_defined?
|
497
530
|
pp.object_address_group(self) do
|
498
531
|
if defined?(@attributes) && @attributes
|
499
|
-
|
500
|
-
pp.seplist(
|
501
|
-
column_value = read_attribute(column_name)
|
532
|
+
attr_names = self.class.attribute_names.select { |name| has_attribute?(name) }
|
533
|
+
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
502
534
|
pp.breakable " "
|
503
535
|
pp.group(1) do
|
504
|
-
pp.text
|
536
|
+
pp.text attr_name
|
505
537
|
pp.text ":"
|
506
538
|
pp.breakable
|
507
|
-
|
539
|
+
value = _read_attribute(attr_name)
|
540
|
+
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
|
541
|
+
pp.pp value
|
508
542
|
end
|
509
543
|
end
|
510
544
|
else
|
@@ -534,26 +568,32 @@ module ActiveRecord
|
|
534
568
|
end
|
535
569
|
|
536
570
|
def init_internals
|
571
|
+
@primary_key = self.class.primary_key
|
537
572
|
@readonly = false
|
538
573
|
@destroyed = false
|
539
574
|
@marked_for_destruction = false
|
540
575
|
@destroyed_by_association = nil
|
541
|
-
@
|
542
|
-
@_start_transaction_state = {}
|
576
|
+
@_start_transaction_state = nil
|
543
577
|
@transaction_state = nil
|
544
|
-
end
|
545
578
|
|
546
|
-
|
579
|
+
self.class.define_attribute_methods
|
547
580
|
end
|
548
581
|
|
549
|
-
def
|
550
|
-
if frozen?
|
551
|
-
@attributes = @attributes.dup
|
552
|
-
end
|
582
|
+
def initialize_internals_callback
|
553
583
|
end
|
554
584
|
|
555
585
|
def custom_inspect_method_defined?
|
556
586
|
self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
|
557
587
|
end
|
588
|
+
|
589
|
+
def inspection_filter
|
590
|
+
@inspection_filter ||= begin
|
591
|
+
mask = DelegateClass(::String).new(ActiveSupport::ParameterFilter::FILTERED)
|
592
|
+
def mask.pretty_print(pp)
|
593
|
+
pp.text __getobj__
|
594
|
+
end
|
595
|
+
ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
|
596
|
+
end
|
597
|
+
end
|
558
598
|
end
|
559
599
|
end
|
@@ -102,27 +102,7 @@ module ActiveRecord
|
|
102
102
|
# # `updated_at` = '2016-10-13T09:59:23-05:00'
|
103
103
|
# # WHERE id IN (10, 15)
|
104
104
|
def update_counters(id, counters)
|
105
|
-
|
106
|
-
|
107
|
-
updates = counters.map do |counter_name, value|
|
108
|
-
operator = value < 0 ? "-" : "+"
|
109
|
-
quoted_column = connection.quote_column_name(counter_name)
|
110
|
-
"#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
|
111
|
-
end
|
112
|
-
|
113
|
-
if touch
|
114
|
-
names = touch if touch != true
|
115
|
-
touch_updates = touch_attributes_with_time(*names)
|
116
|
-
updates << sanitize_sql_for_assignment(touch_updates) unless touch_updates.empty?
|
117
|
-
end
|
118
|
-
|
119
|
-
if id.is_a?(Relation) && self == id.klass
|
120
|
-
relation = id
|
121
|
-
else
|
122
|
-
relation = unscoped.where!(primary_key => id)
|
123
|
-
end
|
124
|
-
|
125
|
-
relation.update_all updates.join(", ")
|
105
|
+
unscoped.where!(primary_key => id).update_counters(counters)
|
126
106
|
end
|
127
107
|
|
128
108
|
# Increment a numeric field by one, via a direct SQL update.
|
@@ -179,14 +159,11 @@ module ActiveRecord
|
|
179
159
|
end
|
180
160
|
|
181
161
|
private
|
182
|
-
|
183
|
-
def _create_record(*)
|
162
|
+
def _create_record(attribute_names = self.attribute_names)
|
184
163
|
id = super
|
185
164
|
|
186
165
|
each_counter_cached_associations do |association|
|
187
|
-
|
188
|
-
association.increment_counters
|
189
|
-
end
|
166
|
+
association.increment_counters
|
190
167
|
end
|
191
168
|
|
192
169
|
id
|
@@ -199,9 +176,7 @@ module ActiveRecord
|
|
199
176
|
each_counter_cached_associations do |association|
|
200
177
|
foreign_key = association.reflection.foreign_key.to_sym
|
201
178
|
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
|
202
|
-
|
203
|
-
association.decrement_counters
|
204
|
-
end
|
179
|
+
association.decrement_counters
|
205
180
|
end
|
206
181
|
end
|
207
182
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# ActiveRecord::Base.configurations will return either a HashConfig or
|
6
|
+
# UrlConfig respectively. It will never return a DatabaseConfig object,
|
7
|
+
# as this is the parent class for the types of database configuration objects.
|
8
|
+
class DatabaseConfig # :nodoc:
|
9
|
+
attr_reader :env_name, :spec_name
|
10
|
+
|
11
|
+
def initialize(env_name, spec_name)
|
12
|
+
@env_name = env_name
|
13
|
+
@spec_name = spec_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def replica?
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def migrations_paths
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
def url_config?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_legacy_hash
|
29
|
+
{ env_name => config }
|
30
|
+
end
|
31
|
+
|
32
|
+
def for_current_env?
|
33
|
+
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# A HashConfig object is created for each database configuration entry that
|
6
|
+
# is created from a hash.
|
7
|
+
#
|
8
|
+
# A hash config:
|
9
|
+
#
|
10
|
+
# { "development" => { "database" => "db_name" } }
|
11
|
+
#
|
12
|
+
# Becomes:
|
13
|
+
#
|
14
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
|
15
|
+
# @env_name="development", @spec_name="primary", @config={"database"=>"db_name"}>
|
16
|
+
#
|
17
|
+
# ==== Options
|
18
|
+
#
|
19
|
+
# * <tt>:env_name</tt> - The Rails environment, i.e. "development".
|
20
|
+
# * <tt>:spec_name</tt> - The specification name. In a standard two-tier
|
21
|
+
# database configuration this will default to "primary". In a multiple
|
22
|
+
# database three-tier database configuration this corresponds to the name
|
23
|
+
# used in the second tier, for example "primary_readonly".
|
24
|
+
# * <tt>:config</tt> - The config hash. This is the hash that contains the
|
25
|
+
# database adapter, name, and other important information for database
|
26
|
+
# connections.
|
27
|
+
class HashConfig < DatabaseConfig
|
28
|
+
attr_reader :config
|
29
|
+
|
30
|
+
def initialize(env_name, spec_name, config)
|
31
|
+
super(env_name, spec_name)
|
32
|
+
@config = config
|
33
|
+
end
|
34
|
+
|
35
|
+
# Determines whether a database configuration is for a replica / readonly
|
36
|
+
# connection. If the +replica+ key is present in the config, +replica?+ will
|
37
|
+
# return +true+.
|
38
|
+
def replica?
|
39
|
+
config["replica"]
|
40
|
+
end
|
41
|
+
|
42
|
+
# The migrations paths for a database configuration. If the
|
43
|
+
# +migrations_paths+ key is present in the config, +migrations_paths+
|
44
|
+
# will return its value.
|
45
|
+
def migrations_paths
|
46
|
+
config["migrations_paths"]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# A UrlConfig object is created for each database configuration
|
6
|
+
# entry that is created from a URL. This can either be a URL string
|
7
|
+
# or a hash with a URL in place of the config hash.
|
8
|
+
#
|
9
|
+
# A URL config:
|
10
|
+
#
|
11
|
+
# postgres://localhost/foo
|
12
|
+
#
|
13
|
+
# Becomes:
|
14
|
+
#
|
15
|
+
# #<ActiveRecord::DatabaseConfigurations::UrlConfig:0x00007fdc3238f340
|
16
|
+
# @env_name="default_env", @spec_name="primary",
|
17
|
+
# @config={"adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost"},
|
18
|
+
# @url="postgres://localhost/foo">
|
19
|
+
#
|
20
|
+
# ==== Options
|
21
|
+
#
|
22
|
+
# * <tt>:env_name</tt> - The Rails environment, ie "development".
|
23
|
+
# * <tt>:spec_name</tt> - The specification name. In a standard two-tier
|
24
|
+
# database configuration this will default to "primary". In a multiple
|
25
|
+
# database three-tier database configuration this corresponds to the name
|
26
|
+
# used in the second tier, for example "primary_readonly".
|
27
|
+
# * <tt>:url</tt> - The database URL.
|
28
|
+
# * <tt>:config</tt> - The config hash. This is the hash that contains the
|
29
|
+
# database adapter, name, and other important information for database
|
30
|
+
# connections.
|
31
|
+
class UrlConfig < DatabaseConfig
|
32
|
+
attr_reader :url, :config
|
33
|
+
|
34
|
+
def initialize(env_name, spec_name, url, config = {})
|
35
|
+
super(env_name, spec_name)
|
36
|
+
@config = build_config(config, url)
|
37
|
+
@url = url
|
38
|
+
end
|
39
|
+
|
40
|
+
def url_config? # :nodoc:
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Determines whether a database configuration is for a replica / readonly
|
45
|
+
# connection. If the +replica+ key is present in the config, +replica?+ will
|
46
|
+
# return +true+.
|
47
|
+
def replica?
|
48
|
+
config["replica"]
|
49
|
+
end
|
50
|
+
|
51
|
+
# The migrations paths for a database configuration. If the
|
52
|
+
# +migrations_paths+ key is present in the config, +migrations_paths+
|
53
|
+
# will return its value.
|
54
|
+
def migrations_paths
|
55
|
+
config["migrations_paths"]
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def build_url_hash(url)
|
61
|
+
if url.nil? || /^jdbc:/.match?(url)
|
62
|
+
{ "url" => url }
|
63
|
+
else
|
64
|
+
ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(url).to_hash
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_config(original_config, url)
|
69
|
+
hash = build_url_hash(url)
|
70
|
+
|
71
|
+
if original_config[env_name]
|
72
|
+
original_config[env_name].merge(hash)
|
73
|
+
else
|
74
|
+
original_config.merge(hash)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|