activerecord 5.2.4.4 → 6.0.0.beta1
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 +300 -725
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +2 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/associations/association.rb +35 -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/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- 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.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- 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 +15 -16
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -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/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +184 -0
- 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 +74 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- 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 +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- 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 +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- 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 +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- 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/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- 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 +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/arel.rb +44 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -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.rb +67 -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/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 +63 -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 +44 -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.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -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.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -85,7 +85,7 @@ module ActiveRecord
|
|
85
85
|
# invert the +command+.
|
86
86
|
def inverse_of(command, args, &block)
|
87
87
|
method = :"invert_#{command}"
|
88
|
-
raise IrreversibleMigration,
|
88
|
+
raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
|
89
89
|
This migration uses #{command}, which is not automatically reversible.
|
90
90
|
To make the migration reversible you can either:
|
91
91
|
1. Define #up and #down methods in place of the #change method.
|
@@ -108,11 +108,17 @@ module ActiveRecord
|
|
108
108
|
yield delegate.update_table_definition(table_name, self)
|
109
109
|
end
|
110
110
|
|
111
|
+
def replay(migration)
|
112
|
+
commands.each do |cmd, args, block|
|
113
|
+
migration.send(cmd, *args, &block)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
111
117
|
private
|
112
118
|
|
113
119
|
module StraightReversions # :nodoc:
|
114
120
|
private
|
115
|
-
{
|
121
|
+
{
|
116
122
|
execute_block: :execute_block,
|
117
123
|
create_table: :drop_table,
|
118
124
|
create_join_table: :drop_join_table,
|
@@ -133,6 +139,17 @@ module ActiveRecord
|
|
133
139
|
|
134
140
|
include StraightReversions
|
135
141
|
|
142
|
+
def invert_transaction(args)
|
143
|
+
sub_recorder = CommandRecorder.new(delegate)
|
144
|
+
sub_recorder.revert { yield }
|
145
|
+
|
146
|
+
invertions_proc = proc {
|
147
|
+
sub_recorder.replay(self)
|
148
|
+
}
|
149
|
+
|
150
|
+
[:transaction, args, invertions_proc]
|
151
|
+
end
|
152
|
+
|
136
153
|
def invert_drop_table(args, &block)
|
137
154
|
if args.size == 1 && block == nil
|
138
155
|
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
@@ -214,11 +231,24 @@ module ActiveRecord
|
|
214
231
|
end
|
215
232
|
|
216
233
|
def invert_remove_foreign_key(args)
|
217
|
-
from_table,
|
218
|
-
|
234
|
+
from_table, options_or_to_table, options_or_nil = args
|
235
|
+
|
236
|
+
to_table = if options_or_to_table.is_a?(Hash)
|
237
|
+
options_or_to_table[:to_table]
|
238
|
+
else
|
239
|
+
options_or_to_table
|
240
|
+
end
|
241
|
+
|
242
|
+
remove_options = if options_or_to_table.is_a?(Hash)
|
243
|
+
options_or_to_table.except(:to_table)
|
244
|
+
else
|
245
|
+
options_or_nil
|
246
|
+
end
|
247
|
+
|
248
|
+
raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
|
219
249
|
|
220
250
|
reversed_args = [from_table, to_table]
|
221
|
-
reversed_args << remove_options if remove_options
|
251
|
+
reversed_args << remove_options if remove_options.present?
|
222
252
|
|
223
253
|
[:add_foreign_key, reversed_args]
|
224
254
|
end
|
@@ -13,22 +13,42 @@ module ActiveRecord
|
|
13
13
|
const_get(name)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
V6_0 = Current
|
17
|
+
|
18
|
+
class V5_2 < V6_0
|
19
|
+
module CommandRecorder
|
20
|
+
def invert_transaction(args, &block)
|
21
|
+
[:transaction, args, block]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def command_recorder
|
28
|
+
recorder = super
|
29
|
+
class << recorder
|
30
|
+
prepend CommandRecorder
|
31
|
+
end
|
32
|
+
recorder
|
33
|
+
end
|
34
|
+
end
|
17
35
|
|
18
36
|
class V5_1 < V5_2
|
19
37
|
def change_column(table_name, column_name, type, options = {})
|
20
|
-
if
|
21
|
-
|
22
|
-
connection.
|
23
|
-
|
24
|
-
|
38
|
+
if adapter_name == "PostgreSQL"
|
39
|
+
clear_cache!
|
40
|
+
sql = connection.send(:change_column_sql, table_name, column_name, type, options)
|
41
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql}"
|
42
|
+
change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
|
43
|
+
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
44
|
+
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
25
45
|
else
|
26
46
|
super
|
27
47
|
end
|
28
48
|
end
|
29
49
|
|
30
50
|
def create_table(table_name, options = {})
|
31
|
-
if
|
51
|
+
if adapter_name == "Mysql2"
|
32
52
|
super(table_name, options: "ENGINE=InnoDB", **options)
|
33
53
|
else
|
34
54
|
super
|
@@ -50,13 +70,13 @@ module ActiveRecord
|
|
50
70
|
end
|
51
71
|
|
52
72
|
def create_table(table_name, options = {})
|
53
|
-
if
|
73
|
+
if adapter_name == "PostgreSQL"
|
54
74
|
if options[:id] == :uuid && !options.key?(:default)
|
55
75
|
options[:default] = "uuid_generate_v4()"
|
56
76
|
end
|
57
77
|
end
|
58
78
|
|
59
|
-
unless
|
79
|
+
unless adapter_name == "Mysql2" && options[:id] == :bigint
|
60
80
|
if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
|
61
81
|
options[:default] = nil
|
62
82
|
end
|
@@ -173,7 +193,7 @@ module ActiveRecord
|
|
173
193
|
if options[:name].present?
|
174
194
|
options[:name].to_s
|
175
195
|
else
|
176
|
-
|
196
|
+
index_name(table_name, column: column_names)
|
177
197
|
end
|
178
198
|
super
|
179
199
|
end
|
@@ -193,17 +213,15 @@ module ActiveRecord
|
|
193
213
|
end
|
194
214
|
|
195
215
|
def index_name_for_remove(table_name, options = {})
|
196
|
-
index_name =
|
216
|
+
index_name = index_name(table_name, options)
|
197
217
|
|
198
|
-
unless
|
218
|
+
unless index_name_exists?(table_name, index_name)
|
199
219
|
if options.is_a?(Hash) && options.has_key?(:name)
|
200
220
|
options_without_column = options.dup
|
201
221
|
options_without_column.delete :column
|
202
|
-
index_name_without_column =
|
222
|
+
index_name_without_column = index_name(table_name, options_without_column)
|
203
223
|
|
204
|
-
if
|
205
|
-
return index_name_without_column
|
206
|
-
end
|
224
|
+
return index_name_without_column if index_name_exists?(table_name, index_name_without_column)
|
207
225
|
end
|
208
226
|
|
209
227
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
|
@@ -102,6 +102,21 @@ module ActiveRecord
|
|
102
102
|
# If true, the default table name for a Product class will be "products". If false, it would just be "product".
|
103
103
|
# See table_name for the full rules on table/class naming. This is true, by default.
|
104
104
|
|
105
|
+
##
|
106
|
+
# :singleton-method: implicit_order_column
|
107
|
+
# :call-seq: implicit_order_column
|
108
|
+
#
|
109
|
+
# The name of the column records are ordered by if no explicit order clause
|
110
|
+
# is used during an ordered finder call. If not set the primary key is used.
|
111
|
+
|
112
|
+
##
|
113
|
+
# :singleton-method: implicit_order_column=
|
114
|
+
# :call-seq: implicit_order_column=(column_name)
|
115
|
+
#
|
116
|
+
# Sets the column to sort records by when no explicit order clause is used
|
117
|
+
# during an ordered finder call. Useful when the primary key is not an
|
118
|
+
# auto-incrementing integer, for example when it's a UUID. Note that using
|
119
|
+
# a non-unique column can result in non-deterministic results.
|
105
120
|
included do
|
106
121
|
mattr_accessor :primary_key_prefix_type, instance_writer: false
|
107
122
|
|
@@ -110,6 +125,7 @@ module ActiveRecord
|
|
110
125
|
class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
|
111
126
|
class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
|
112
127
|
class_attribute :pluralize_table_names, instance_writer: false, default: true
|
128
|
+
class_attribute :implicit_order_column, instance_accessor: false
|
113
129
|
|
114
130
|
self.protected_environments = ["production"]
|
115
131
|
self.inheritance_column = "type"
|
@@ -218,11 +234,11 @@ module ActiveRecord
|
|
218
234
|
end
|
219
235
|
|
220
236
|
def full_table_name_prefix #:nodoc:
|
221
|
-
(
|
237
|
+
(module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
|
222
238
|
end
|
223
239
|
|
224
240
|
def full_table_name_suffix #:nodoc:
|
225
|
-
(
|
241
|
+
(module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
|
226
242
|
end
|
227
243
|
|
228
244
|
# The array of names of environments where destructive actions should be prohibited. By default,
|
@@ -276,7 +292,7 @@ module ActiveRecord
|
|
276
292
|
end
|
277
293
|
|
278
294
|
def sequence_name
|
279
|
-
if base_class
|
295
|
+
if base_class?
|
280
296
|
@sequence_name ||= reset_sequence_name
|
281
297
|
else
|
282
298
|
(@sequence_name ||= nil) || base_class.sequence_name
|
@@ -388,6 +404,11 @@ module ActiveRecord
|
|
388
404
|
@column_names ||= columns.map(&:name)
|
389
405
|
end
|
390
406
|
|
407
|
+
def symbol_column_to_string(name_symbol) # :nodoc:
|
408
|
+
@symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
|
409
|
+
@symbol_column_to_string_name_hash[name_symbol]
|
410
|
+
end
|
411
|
+
|
391
412
|
# Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
|
392
413
|
# and columns used for single table inheritance have been removed.
|
393
414
|
def content_columns
|
@@ -477,6 +498,7 @@ module ActiveRecord
|
|
477
498
|
def reload_schema_from_cache
|
478
499
|
@arel_table = nil
|
479
500
|
@column_names = nil
|
501
|
+
@symbol_column_to_string_name_hash = nil
|
480
502
|
@attribute_types = nil
|
481
503
|
@content_columns = nil
|
482
504
|
@default_attributes = nil
|
@@ -501,19 +523,18 @@ module ActiveRecord
|
|
501
523
|
|
502
524
|
# Computes and returns a table name according to default conventions.
|
503
525
|
def compute_table_name
|
504
|
-
|
505
|
-
if self == base
|
526
|
+
if base_class?
|
506
527
|
# Nested classes are prefixed with singular parent table name.
|
507
|
-
if
|
508
|
-
contained =
|
509
|
-
contained = contained.singularize if
|
528
|
+
if module_parent < Base && !module_parent.abstract_class?
|
529
|
+
contained = module_parent.table_name
|
530
|
+
contained = contained.singularize if module_parent.pluralize_table_names
|
510
531
|
contained += "_"
|
511
532
|
end
|
512
533
|
|
513
534
|
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
|
514
535
|
else
|
515
536
|
# STI subclasses always use their superclass' table.
|
516
|
-
|
537
|
+
base_class.table_name
|
517
538
|
end
|
518
539
|
end
|
519
540
|
end
|
@@ -426,7 +426,7 @@ module ActiveRecord
|
|
426
426
|
existing_record.assign_attributes(assignable_attributes)
|
427
427
|
association(association_name).initialize_attributes(existing_record)
|
428
428
|
else
|
429
|
-
method = "build_#{association_name}"
|
429
|
+
method = :"build_#{association_name}"
|
430
430
|
if respond_to?(method)
|
431
431
|
send(method, assignable_attributes)
|
432
432
|
else
|
@@ -501,7 +501,7 @@ module ActiveRecord
|
|
501
501
|
|
502
502
|
if attributes["id"].blank?
|
503
503
|
unless reject_new_record?(association_name, attributes)
|
504
|
-
association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
504
|
+
association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
|
505
505
|
end
|
506
506
|
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
|
507
507
|
unless call_reject_if(association_name, attributes)
|
@@ -43,6 +43,13 @@ module ActiveRecord
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
|
47
|
+
#
|
48
|
+
# Project.no_touching do
|
49
|
+
# Project.first.no_touching? # true
|
50
|
+
# Message.first.no_touching? # false
|
51
|
+
# end
|
52
|
+
#
|
46
53
|
def no_touching?
|
47
54
|
NoTouching.applied_to?(self.class)
|
48
55
|
end
|
@@ -67,8 +67,7 @@ module ActiveRecord
|
|
67
67
|
# how this "single-table" inheritance mapping is implemented.
|
68
68
|
def instantiate(attributes, column_types = {}, &block)
|
69
69
|
klass = discriminate_class_for_record(attributes)
|
70
|
-
|
71
|
-
klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
|
70
|
+
instantiate_instance_of(klass, attributes, column_types, &block)
|
72
71
|
end
|
73
72
|
|
74
73
|
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
@@ -178,7 +177,7 @@ module ActiveRecord
|
|
178
177
|
end
|
179
178
|
|
180
179
|
if values.empty?
|
181
|
-
im = arel_table.compile_insert(connection.empty_insert_statement_value)
|
180
|
+
im = arel_table.compile_insert(connection.empty_insert_statement_value(primary_key))
|
182
181
|
im.into arel_table
|
183
182
|
else
|
184
183
|
im = arel_table.compile_insert(_substitute_values(values))
|
@@ -208,6 +207,13 @@ module ActiveRecord
|
|
208
207
|
end
|
209
208
|
|
210
209
|
private
|
210
|
+
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
211
|
+
# new instance of the class. Accepts only keys as strings.
|
212
|
+
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
213
|
+
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
214
|
+
klass.allocate.init_with_attributes(attributes, &block)
|
215
|
+
end
|
216
|
+
|
211
217
|
# Called by +instantiate+ to decide which class to use for a new
|
212
218
|
# record instance.
|
213
219
|
#
|
@@ -430,6 +436,7 @@ module ActiveRecord
|
|
430
436
|
end
|
431
437
|
|
432
438
|
alias update_attributes update
|
439
|
+
deprecate :update_attributes
|
433
440
|
|
434
441
|
# Updates its receiver just like #update but calls #save! instead
|
435
442
|
# of +save+, so an exception is raised if the record is invalid and saving will fail.
|
@@ -443,6 +450,7 @@ module ActiveRecord
|
|
443
450
|
end
|
444
451
|
|
445
452
|
alias update_attributes! update!
|
453
|
+
deprecate :update_attributes!
|
446
454
|
|
447
455
|
# Equivalent to <code>update_columns(name => value)</code>.
|
448
456
|
def update_column(name, value)
|
@@ -709,7 +717,6 @@ module ActiveRecord
|
|
709
717
|
# Updates the associated record with values matching those of the instance attributes.
|
710
718
|
# Returns the number of affected rows.
|
711
719
|
def _update_record(attribute_names = self.attribute_names)
|
712
|
-
attribute_names &= self.class.column_names
|
713
720
|
attribute_names = attributes_for_update(attribute_names)
|
714
721
|
|
715
722
|
if attribute_names.empty?
|
@@ -728,10 +735,12 @@ module ActiveRecord
|
|
728
735
|
# Creates a record with values matching those of the instance attributes
|
729
736
|
# and returns its id.
|
730
737
|
def _create_record(attribute_names = self.attribute_names)
|
731
|
-
attribute_names
|
732
|
-
|
738
|
+
attribute_names = attributes_for_create(attribute_names)
|
739
|
+
|
740
|
+
new_id = self.class._insert_record(
|
741
|
+
attributes_with_values(attribute_names)
|
742
|
+
)
|
733
743
|
|
734
|
-
new_id = self.class._insert_record(attributes_values)
|
735
744
|
self.id ||= new_id if self.class.primary_key
|
736
745
|
|
737
746
|
@new_record = false
|
@@ -752,6 +761,8 @@ module ActiveRecord
|
|
752
761
|
@_association_destroy_exception = nil
|
753
762
|
end
|
754
763
|
|
764
|
+
# The name of the method used to touch a +belongs_to+ association when the
|
765
|
+
# +:touch+ option is used.
|
755
766
|
def belongs_to_touch_method
|
756
767
|
:touch
|
757
768
|
end
|
@@ -26,15 +26,22 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.run
|
29
|
-
|
30
|
-
|
29
|
+
pools = []
|
30
|
+
|
31
|
+
ActiveRecord::Base.connection_handlers.each do |key, handler|
|
32
|
+
pools << handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
|
33
|
+
end
|
34
|
+
|
35
|
+
pools.flatten
|
31
36
|
end
|
32
37
|
|
33
38
|
def self.complete(pools)
|
34
39
|
pools.each { |pool| pool.disable_query_cache! }
|
35
40
|
|
36
|
-
ActiveRecord::Base.
|
37
|
-
|
41
|
+
ActiveRecord::Base.connection_handlers.each do |_, handler|
|
42
|
+
handler.connection_pool_list.each do |pool|
|
43
|
+
pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
|
6
6
|
delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all
|
7
7
|
delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
|
8
|
-
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
8
|
+
delegate :find_or_create_by, :find_or_create_by!, :create_or_find_by, :create_or_find_by!, :find_or_initialize_by, to: :all
|
9
9
|
delegate :find_by, :find_by!, to: :all
|
10
10
|
delegate :destroy_all, :delete_all, :update_all, to: :all
|
11
11
|
delegate :find_each, :find_in_batches, :in_batches, to: :all
|
@@ -13,20 +13,20 @@ module ActiveRecord
|
|
13
13
|
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
|
14
14
|
:having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
|
15
15
|
delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
|
16
|
-
delegate :pluck, :ids, to: :all
|
16
|
+
delegate :pluck, :pick, :ids, to: :all
|
17
17
|
|
18
18
|
# Executes a custom SQL query against your database and returns all the results. The results will
|
19
|
-
# be returned as an array with
|
20
|
-
# this method from.
|
19
|
+
# be returned as an array, with the requested columns encapsulated as attributes of the model you call
|
20
|
+
# this method from. For example, if you call <tt>Product.find_by_sql</tt>, then the results will be returned in
|
21
21
|
# a +Product+ object with the attributes you specified in the SQL query.
|
22
22
|
#
|
23
|
-
# If you call a complicated SQL query which spans multiple tables the columns specified by the
|
23
|
+
# If you call a complicated SQL query which spans multiple tables, the columns specified by the
|
24
24
|
# SELECT will be attributes of the model, whether or not they are columns of the corresponding
|
25
25
|
# table.
|
26
26
|
#
|
27
|
-
# The +sql+ parameter is a full SQL query as a string. It will be called as is
|
28
|
-
# no database agnostic conversions performed. This should be a last resort because using
|
29
|
-
#
|
27
|
+
# The +sql+ parameter is a full SQL query as a string. It will be called as is; there will be
|
28
|
+
# no database agnostic conversions performed. This should be a last resort because using
|
29
|
+
# database-specific terms will lock you into using that particular database engine, or require you to
|
30
30
|
# change your call if you switch engines.
|
31
31
|
#
|
32
32
|
# # A simple SQL query spanning multiple tables
|
@@ -40,7 +40,8 @@ module ActiveRecord
|
|
40
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
41
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
42
42
|
column_types = result_set.column_types.dup
|
43
|
-
|
43
|
+
cached_columns_hash = connection.schema_cache.columns_hash(table_name)
|
44
|
+
cached_columns_hash.each_key { |k| column_types.delete k }
|
44
45
|
message_bus = ActiveSupport::Notifications.instrumenter
|
45
46
|
|
46
47
|
payload = {
|
@@ -49,13 +50,20 @@ module ActiveRecord
|
|
49
50
|
}
|
50
51
|
|
51
52
|
message_bus.instrument("instantiation.active_record", payload) do
|
52
|
-
result_set.
|
53
|
+
if result_set.includes_column?(inheritance_column)
|
54
|
+
result_set.map { |record| instantiate(record, column_types, &block) }
|
55
|
+
else
|
56
|
+
# Instantiate a homogeneous set
|
57
|
+
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
58
|
+
end
|
53
59
|
end
|
54
60
|
end
|
55
61
|
|
56
62
|
# Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
|
57
63
|
# The use of this method should be restricted to complicated SQL queries that can't be executed
|
58
|
-
# using the ActiveRecord::Calculations class methods. Look into those before using this
|
64
|
+
# using the ActiveRecord::Calculations class methods. Look into those before using this method,
|
65
|
+
# as it could lock you into a specific database engine or require a code change to switch
|
66
|
+
# database engines.
|
59
67
|
#
|
60
68
|
# Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
|
61
69
|
# # => 12
|