activerecord 5.2.3.rc1 → 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 +326 -696
- 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 +1 -1
- 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 +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.rb +15 -20
- data/lib/active_record/associations/join_dependency/join_association.rb +6 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +31 -28
- 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 +1 -1
- 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 +10 -14
- 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 +14 -11
- 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 +40 -26
- 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 +93 -60
- 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 +46 -34
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +34 -23
- 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 +26 -47
- 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 +8 -1
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/statement_cache.rb +30 -3
- 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 +2 -21
- 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 +101 -23
@@ -14,38 +14,39 @@ module ActiveRecord
|
|
14
14
|
[key] if key
|
15
15
|
end
|
16
16
|
|
17
|
-
# Returns the primary key value.
|
17
|
+
# Returns the primary key column's value.
|
18
18
|
def id
|
19
19
|
sync_with_transaction_state
|
20
20
|
primary_key = self.class.primary_key
|
21
21
|
_read_attribute(primary_key) if primary_key
|
22
22
|
end
|
23
23
|
|
24
|
-
# Sets the primary key value.
|
24
|
+
# Sets the primary key column's value.
|
25
25
|
def id=(value)
|
26
26
|
sync_with_transaction_state
|
27
27
|
primary_key = self.class.primary_key
|
28
28
|
_write_attribute(primary_key, value) if primary_key
|
29
29
|
end
|
30
30
|
|
31
|
-
# Queries the primary key value.
|
31
|
+
# Queries the primary key column's value.
|
32
32
|
def id?
|
33
33
|
sync_with_transaction_state
|
34
34
|
query_attribute(self.class.primary_key)
|
35
35
|
end
|
36
36
|
|
37
|
-
# Returns the primary key value before type cast.
|
37
|
+
# Returns the primary key column's value before type cast.
|
38
38
|
def id_before_type_cast
|
39
39
|
sync_with_transaction_state
|
40
40
|
read_attribute_before_type_cast(self.class.primary_key)
|
41
41
|
end
|
42
42
|
|
43
|
-
# Returns the primary key previous value.
|
43
|
+
# Returns the primary key column's previous value.
|
44
44
|
def id_was
|
45
45
|
sync_with_transaction_state
|
46
46
|
attribute_was(self.class.primary_key)
|
47
47
|
end
|
48
48
|
|
49
|
+
# Returns the primary key column's value from the database.
|
49
50
|
def id_in_database
|
50
51
|
sync_with_transaction_state
|
51
52
|
attribute_in_database(self.class.primary_key)
|
@@ -83,7 +84,7 @@ module ActiveRecord
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def reset_primary_key #:nodoc:
|
86
|
-
if
|
87
|
+
if base_class?
|
87
88
|
self.primary_key = get_primary_key(base_class.name)
|
88
89
|
else
|
89
90
|
self.primary_key = base_class.primary_key
|
@@ -131,7 +132,7 @@ module ActiveRecord
|
|
131
132
|
def suppress_composite_primary_key(pk)
|
132
133
|
return pk unless pk.is_a?(Array)
|
133
134
|
|
134
|
-
warn
|
135
|
+
warn <<~WARNING
|
135
136
|
WARNING: Active Record does not support composite primary key.
|
136
137
|
|
137
138
|
#{table_name} has composite primary key. Composite primary key is ignored.
|
@@ -8,42 +8,19 @@ module ActiveRecord
|
|
8
8
|
module ClassMethods # :nodoc:
|
9
9
|
private
|
10
10
|
|
11
|
-
# We want to generate the methods via module_eval rather than
|
12
|
-
# define_method, because define_method is slower on dispatch.
|
13
|
-
# Evaluating many similar methods may use more memory as the instruction
|
14
|
-
# sequences are duplicated and cached (in MRI). define_method may
|
15
|
-
# be slower on dispatch, but if you're careful about the closure
|
16
|
-
# created, then define_method will consume much less memory.
|
17
|
-
#
|
18
|
-
# But sometimes the database might return columns with
|
19
|
-
# characters that are not allowed in normal method names (like
|
20
|
-
# 'my_column(omg)'. So to work around this we first define with
|
21
|
-
# the __temp__ identifier, and then use alias method to rename
|
22
|
-
# it to what we want.
|
23
|
-
#
|
24
|
-
# We are also defining a constant to hold the frozen string of
|
25
|
-
# the attribute name. Using a constant means that we do not have
|
26
|
-
# to allocate an object on each call to the attribute method.
|
27
|
-
# Making it frozen means that it doesn't get duped when used to
|
28
|
-
# key the @attributes in read_attribute.
|
29
11
|
def define_method_attribute(name)
|
30
|
-
safe_name = name.unpack("h*".freeze).first
|
31
|
-
temp_method = "__temp__#{safe_name}"
|
32
|
-
|
33
|
-
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
34
12
|
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
|
35
13
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
undef_method temp_method
|
14
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
15
|
+
generated_attribute_methods, name
|
16
|
+
) do |temp_method_name, attr_name_expr|
|
17
|
+
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
18
|
+
def #{temp_method_name}
|
19
|
+
#{sync_with_transaction_state}
|
20
|
+
name = #{attr_name_expr}
|
21
|
+
_read_attribute(name) { |n| missing_attribute(n, caller) }
|
22
|
+
end
|
23
|
+
RUBY
|
47
24
|
end
|
48
25
|
end
|
49
26
|
end
|
@@ -52,30 +29,21 @@ module ActiveRecord
|
|
52
29
|
# it has been typecast (for example, "2004-12-12" in a date column is cast
|
53
30
|
# to a date object, like Date.new(2004, 12, 12)).
|
54
31
|
def read_attribute(attr_name, &block)
|
55
|
-
name =
|
56
|
-
|
57
|
-
|
58
|
-
attr_name.to_s
|
32
|
+
name = attr_name.to_s
|
33
|
+
if self.class.attribute_alias?(name)
|
34
|
+
name = self.class.attribute_alias(name)
|
59
35
|
end
|
60
36
|
|
61
37
|
primary_key = self.class.primary_key
|
62
|
-
name = primary_key if name == "id"
|
38
|
+
name = primary_key if name == "id" && primary_key
|
63
39
|
sync_with_transaction_state if name == primary_key
|
64
40
|
_read_attribute(name, &block)
|
65
41
|
end
|
66
42
|
|
67
43
|
# This method exists to avoid the expensive primary_key check internally, without
|
68
44
|
# breaking compatibility with the read_attribute API
|
69
|
-
|
70
|
-
|
71
|
-
# https://github.com/jruby/jruby/pull/2562
|
72
|
-
def _read_attribute(attr_name, &block) # :nodoc:
|
73
|
-
@attributes.fetch_value(attr_name.to_s, &block)
|
74
|
-
end
|
75
|
-
else
|
76
|
-
def _read_attribute(attr_name) # :nodoc:
|
77
|
-
@attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
|
78
|
-
end
|
45
|
+
def _read_attribute(attr_name, &block) # :nodoc
|
46
|
+
@attributes.fetch_value(attr_name.to_s, &block)
|
79
47
|
end
|
80
48
|
|
81
49
|
alias :attribute :_read_attribute
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
|
8
8
|
class ColumnNotSerializableError < StandardError
|
9
9
|
def initialize(name, type)
|
10
|
-
super
|
10
|
+
super <<~EOS
|
11
11
|
Column `#{name}` of type #{type.class} does not support `serialize` feature.
|
12
12
|
Usually it means that you are trying to use `serialize`
|
13
13
|
on a column that already implements serialization natively.
|
@@ -73,7 +73,7 @@ module ActiveRecord
|
|
73
73
|
# `skip_time_zone_conversion_for_attributes` would not be picked up.
|
74
74
|
subclass.class_eval do
|
75
75
|
matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
|
76
|
-
decorate_matching_attribute_types(matcher,
|
76
|
+
decorate_matching_attribute_types(matcher, "_time_zone_conversion") do |type|
|
77
77
|
TimeZoneConverter.new(type)
|
78
78
|
end
|
79
79
|
end
|
@@ -13,19 +13,19 @@ module ActiveRecord
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def define_method_attribute=(name)
|
16
|
-
safe_name = name.unpack("h*".freeze).first
|
17
|
-
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
18
16
|
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
19
|
+
generated_attribute_methods, name, writer: true,
|
20
|
+
) do |temp_method_name, attr_name_expr|
|
21
|
+
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
22
|
+
def #{temp_method_name}(value)
|
23
|
+
name = #{attr_name_expr}
|
24
|
+
#{sync_with_transaction_state}
|
25
|
+
_write_attribute(name, value)
|
26
|
+
end
|
27
|
+
RUBY
|
28
|
+
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -33,14 +33,13 @@ module ActiveRecord
|
|
33
33
|
# specified +value+. Empty strings for Integer and Float columns are
|
34
34
|
# turned into +nil+.
|
35
35
|
def write_attribute(attr_name, value)
|
36
|
-
name =
|
37
|
-
|
38
|
-
|
39
|
-
attr_name.to_s
|
36
|
+
name = attr_name.to_s
|
37
|
+
if self.class.attribute_alias?(name)
|
38
|
+
name = self.class.attribute_alias(name)
|
40
39
|
end
|
41
40
|
|
42
41
|
primary_key = self.class.primary_key
|
43
|
-
name = primary_key if name == "id"
|
42
|
+
name = primary_key if name == "id" && primary_key
|
44
43
|
sync_with_transaction_state if name == primary_key
|
45
44
|
_write_attribute(name, value)
|
46
45
|
end
|
@@ -149,7 +149,7 @@ module ActiveRecord
|
|
149
149
|
private
|
150
150
|
|
151
151
|
def define_non_cyclic_method(name, &block)
|
152
|
-
return if
|
152
|
+
return if instance_methods(false).include?(name)
|
153
153
|
define_method(name) do |*args|
|
154
154
|
result = true; @_already_called ||= {}
|
155
155
|
# Loop prevention for validation of associations
|
data/lib/active_record/base.rb
CHANGED
@@ -9,7 +9,6 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
9
9
|
require "active_support/core_ext/array/extract_options"
|
10
10
|
require "active_support/core_ext/hash/deep_merge"
|
11
11
|
require "active_support/core_ext/hash/slice"
|
12
|
-
require "active_support/core_ext/hash/transform_values"
|
13
12
|
require "active_support/core_ext/string/behavior"
|
14
13
|
require "active_support/core_ext/kernel/singleton_class"
|
15
14
|
require "active_support/core_ext/module/introspection"
|
@@ -23,6 +22,7 @@ require "active_record/explain_subscriber"
|
|
23
22
|
require "active_record/relation/delegation"
|
24
23
|
require "active_record/attributes"
|
25
24
|
require "active_record/type_caster"
|
25
|
+
require "active_record/database_configurations"
|
26
26
|
|
27
27
|
module ActiveRecord #:nodoc:
|
28
28
|
# = Active Record
|
@@ -289,6 +289,7 @@ module ActiveRecord #:nodoc:
|
|
289
289
|
extend Enum
|
290
290
|
extend Delegation::DelegateCache
|
291
291
|
extend CollectionCacheKey
|
292
|
+
extend Aggregations::ClassMethods
|
292
293
|
|
293
294
|
include Core
|
294
295
|
include Persistence
|
@@ -314,7 +315,6 @@ module ActiveRecord #:nodoc:
|
|
314
315
|
include ActiveModel::SecurePassword
|
315
316
|
include AutosaveAssociation
|
316
317
|
include NestedAttributes
|
317
|
-
include Aggregations
|
318
318
|
include Transactions
|
319
319
|
include TouchLater
|
320
320
|
include NoTouching
|
@@ -75,21 +75,7 @@ module ActiveRecord
|
|
75
75
|
# end
|
76
76
|
#
|
77
77
|
# Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
|
78
|
-
# run, both +destroy_author+ and +destroy_readers+ are called.
|
79
|
-
# where the +before_destroy+ method is overridden:
|
80
|
-
#
|
81
|
-
# class Topic < ActiveRecord::Base
|
82
|
-
# def before_destroy() destroy_author end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# class Reply < Topic
|
86
|
-
# def before_destroy() destroy_readers end
|
87
|
-
# end
|
88
|
-
#
|
89
|
-
# In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
|
90
|
-
# So, use the callback macros when you want to ensure that a certain callback is called for the entire
|
91
|
-
# hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
|
92
|
-
# to decide whether they want to call +super+ and trigger the inherited callbacks.
|
78
|
+
# run, both +destroy_author+ and +destroy_readers+ are called.
|
93
79
|
#
|
94
80
|
# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
|
95
81
|
# callbacks before specifying the associations. Otherwise, you might trigger the loading of a
|
@@ -109,7 +95,7 @@ module ActiveRecord
|
|
109
95
|
#
|
110
96
|
# private
|
111
97
|
# def delete_parents
|
112
|
-
# self.class.
|
98
|
+
# self.class.where(parent_id: id).delete_all
|
113
99
|
# end
|
114
100
|
# end
|
115
101
|
#
|
@@ -142,7 +128,7 @@ module ActiveRecord
|
|
142
128
|
# end
|
143
129
|
# end
|
144
130
|
#
|
145
|
-
# So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
|
131
|
+
# So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
|
146
132
|
# a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
|
147
133
|
# initialization data such as the name of the attribute to work with:
|
148
134
|
#
|
@@ -16,7 +16,7 @@ module ActiveRecord
|
|
16
16
|
collection = collection.send(:apply_join_dependency)
|
17
17
|
end
|
18
18
|
column_type = type_for_attribute(timestamp_column)
|
19
|
-
column = connection.
|
19
|
+
column = connection.visitor.compile(collection.arel_attribute(timestamp_column))
|
20
20
|
select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
|
21
21
|
|
22
22
|
if collection.has_limit_or_offset?
|
@@ -731,7 +731,7 @@ module ActiveRecord
|
|
731
731
|
# this block can't be easily moved into attempt_to_checkout_all_existing_connections's
|
732
732
|
# rescue block, because doing so would put it outside of synchronize section, without
|
733
733
|
# being in a critical section thread_report might become inaccurate
|
734
|
-
msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds"
|
734
|
+
msg = +"could not obtain ownership of all database connections in #{checkout_timeout} seconds"
|
735
735
|
|
736
736
|
thread_report = []
|
737
737
|
@connections.each do |conn|
|
@@ -915,16 +915,6 @@ module ActiveRecord
|
|
915
915
|
# about the model. The model needs to pass a specification name to the handler,
|
916
916
|
# in order to look up the correct connection pool.
|
917
917
|
class ConnectionHandler
|
918
|
-
def self.create_owner_to_pool # :nodoc:
|
919
|
-
Concurrent::Map.new(initial_capacity: 2) do |h, k|
|
920
|
-
# Discard the parent's connection pools immediately; we have no need
|
921
|
-
# of them
|
922
|
-
discard_unowned_pools(h)
|
923
|
-
|
924
|
-
h[k] = Concurrent::Map.new(initial_capacity: 2)
|
925
|
-
end
|
926
|
-
end
|
927
|
-
|
928
918
|
def self.unowned_pool_finalizer(pid_map) # :nodoc:
|
929
919
|
lambda do |_|
|
930
920
|
discard_unowned_pools(pid_map)
|
@@ -939,7 +929,13 @@ module ActiveRecord
|
|
939
929
|
|
940
930
|
def initialize
|
941
931
|
# These caches are keyed by spec.name (ConnectionSpecification#name).
|
942
|
-
@owner_to_pool =
|
932
|
+
@owner_to_pool = Concurrent::Map.new(initial_capacity: 2) do |h, k|
|
933
|
+
# Discard the parent's connection pools immediately; we have no need
|
934
|
+
# of them
|
935
|
+
ConnectionHandler.discard_unowned_pools(h)
|
936
|
+
|
937
|
+
h[k] = Concurrent::Map.new(initial_capacity: 2)
|
938
|
+
end
|
943
939
|
|
944
940
|
# Backup finalizer: if the forked child never needed a pool, the above
|
945
941
|
# early discard has not occurred
|
@@ -1017,8 +1013,8 @@ module ActiveRecord
|
|
1017
1013
|
# Returns true if a connection that's accessible to this class has
|
1018
1014
|
# already been opened.
|
1019
1015
|
def connected?(spec_name)
|
1020
|
-
|
1021
|
-
|
1016
|
+
pool = retrieve_connection_pool(spec_name)
|
1017
|
+
pool && pool.connected?
|
1022
1018
|
end
|
1023
1019
|
|
1024
1020
|
# Remove the connection for this class. This will close the active
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters # :nodoc:
|
5
7
|
module DatabaseLimits
|
@@ -12,11 +14,13 @@ module ActiveRecord
|
|
12
14
|
def column_name_length
|
13
15
|
64
|
14
16
|
end
|
17
|
+
deprecate :column_name_length
|
15
18
|
|
16
19
|
# Returns the maximum length of a table name.
|
17
20
|
def table_name_length
|
18
21
|
64
|
19
22
|
end
|
23
|
+
deprecate :table_name_length
|
20
24
|
|
21
25
|
# Returns the maximum allowed length for an index name. This
|
22
26
|
# limit is enforced by \Rails and is less than or equal to
|
@@ -36,16 +40,19 @@ module ActiveRecord
|
|
36
40
|
def columns_per_table
|
37
41
|
1024
|
38
42
|
end
|
43
|
+
deprecate :columns_per_table
|
39
44
|
|
40
45
|
# Returns the maximum number of indexes per table.
|
41
46
|
def indexes_per_table
|
42
47
|
16
|
43
48
|
end
|
49
|
+
deprecate :indexes_per_table
|
44
50
|
|
45
51
|
# Returns the maximum number of columns in a multicolumn index.
|
46
52
|
def columns_per_multicolumn_index
|
47
53
|
16
|
48
54
|
end
|
55
|
+
deprecate :columns_per_multicolumn_index
|
49
56
|
|
50
57
|
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
51
58
|
# +nil+ means no limit.
|
@@ -57,11 +64,13 @@ module ActiveRecord
|
|
57
64
|
def sql_query_length
|
58
65
|
1048575
|
59
66
|
end
|
67
|
+
deprecate :sql_query_length
|
60
68
|
|
61
69
|
# Returns maximum number of joins in a single query.
|
62
70
|
def joins_per_query
|
63
71
|
256
|
64
72
|
end
|
73
|
+
deprecate :joins_per_query
|
65
74
|
|
66
75
|
private
|
67
76
|
def bind_params_length
|
@@ -20,22 +20,9 @@ module ActiveRecord
|
|
20
20
|
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
21
|
"The values must be stored on the AST directly"
|
22
22
|
end
|
23
|
-
|
24
|
-
|
25
|
-
sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
|
26
|
-
|
27
|
-
if binds.length > bind_params_length
|
28
|
-
unprepared_statement do
|
29
|
-
sql, binds = to_sql_and_binds(arel_or_sql_string)
|
30
|
-
visitor.preparable = false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
else
|
34
|
-
sql = visitor.accept(arel_or_sql_string.ast, collector).value
|
35
|
-
end
|
36
|
-
[sql.freeze, binds]
|
23
|
+
sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
|
24
|
+
[sql.freeze, binds || []]
|
37
25
|
else
|
38
|
-
visitor.preparable = false if prepared_statements
|
39
26
|
[arel_or_sql_string.dup.freeze, binds]
|
40
27
|
end
|
41
28
|
end
|
@@ -45,11 +32,11 @@ module ActiveRecord
|
|
45
32
|
# can be used to query the database repeatedly.
|
46
33
|
def cacheable_query(klass, arel) # :nodoc:
|
47
34
|
if prepared_statements
|
48
|
-
sql, binds = visitor.
|
35
|
+
sql, binds = visitor.compile(arel.ast, collector)
|
49
36
|
query = klass.query(sql)
|
50
37
|
else
|
51
|
-
collector =
|
52
|
-
parts, binds = visitor.
|
38
|
+
collector = klass.partial_query_collector
|
39
|
+
parts, binds = visitor.compile(arel.ast, collector)
|
53
40
|
query = klass.partial_query(parts)
|
54
41
|
end
|
55
42
|
[query, binds]
|
@@ -60,8 +47,13 @@ module ActiveRecord
|
|
60
47
|
arel = arel_from_relation(arel)
|
61
48
|
sql, binds = to_sql_and_binds(arel, binds)
|
62
49
|
|
63
|
-
if preparable.nil?
|
64
|
-
preparable =
|
50
|
+
if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
|
51
|
+
preparable = false
|
52
|
+
elsif binds.length > bind_params_length
|
53
|
+
sql, binds = unprepared_statement { to_sql_and_binds(arel) }
|
54
|
+
preparable = false
|
55
|
+
else
|
56
|
+
preparable = visitor.preparable
|
65
57
|
end
|
66
58
|
|
67
59
|
if prepared_statements && preparable
|
@@ -106,6 +98,11 @@ module ActiveRecord
|
|
106
98
|
exec_query(sql, name).rows
|
107
99
|
end
|
108
100
|
|
101
|
+
# Determines whether the SQL statement is a write query.
|
102
|
+
def write_query?(sql)
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
|
109
106
|
# Executes the SQL statement in the context of this connection and returns
|
110
107
|
# the raw result from the connection adapter.
|
111
108
|
# Note: depending on your database connector, the result returned by this
|
@@ -126,7 +123,7 @@ module ActiveRecord
|
|
126
123
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
127
124
|
# the executed +sql+ statement.
|
128
125
|
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
129
|
-
sql, binds = sql_for_insert(sql, pk,
|
126
|
+
sql, binds = sql_for_insert(sql, pk, sequence_name, binds)
|
130
127
|
exec_query(sql, name, binds)
|
131
128
|
end
|
132
129
|
|
@@ -176,13 +173,6 @@ module ActiveRecord
|
|
176
173
|
exec_delete(sql, name, binds)
|
177
174
|
end
|
178
175
|
|
179
|
-
# Returns +true+ when the connection adapter supports prepared statement
|
180
|
-
# caching, otherwise returns +false+
|
181
|
-
def supports_statement_cache? # :nodoc:
|
182
|
-
true
|
183
|
-
end
|
184
|
-
deprecate :supports_statement_cache?
|
185
|
-
|
186
176
|
# Runs the given block in a database transaction, and returns the result
|
187
177
|
# of the block.
|
188
178
|
#
|
@@ -272,7 +262,9 @@ module ActiveRecord
|
|
272
262
|
|
273
263
|
attr_reader :transaction_manager #:nodoc:
|
274
264
|
|
275
|
-
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
265
|
+
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
266
|
+
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
267
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
|
276
268
|
|
277
269
|
def transaction_open?
|
278
270
|
current_transaction.open?
|
@@ -337,7 +329,7 @@ module ActiveRecord
|
|
337
329
|
|
338
330
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
339
331
|
# something beyond a simple insert (eg. Oracle).
|
340
|
-
# Most of adapters should implement `
|
332
|
+
# Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
|
341
333
|
# We keep this method to provide fallback
|
342
334
|
# for databases like sqlite that do not support bulk inserts.
|
343
335
|
def insert_fixture(fixture, table_name)
|
@@ -366,18 +358,6 @@ module ActiveRecord
|
|
366
358
|
execute manager.to_sql, "Fixture Insert"
|
367
359
|
end
|
368
360
|
|
369
|
-
# Inserts a set of fixtures into the table. Overridden in adapters that require
|
370
|
-
# something beyond a simple insert (eg. Oracle).
|
371
|
-
def insert_fixtures(fixtures, table_name)
|
372
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
373
|
-
`insert_fixtures` is deprecated and will be removed in the next version of Rails.
|
374
|
-
Consider using `insert_fixtures_set` for performance improvement.
|
375
|
-
MSG
|
376
|
-
return if fixtures.empty?
|
377
|
-
|
378
|
-
execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
|
379
|
-
end
|
380
|
-
|
381
361
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
382
362
|
fixture_inserts = fixture_set.map do |table_name, fixtures|
|
383
363
|
next if fixtures.empty?
|
@@ -385,7 +365,7 @@ module ActiveRecord
|
|
385
365
|
build_fixture_sql(fixtures, table_name)
|
386
366
|
end.compact
|
387
367
|
|
388
|
-
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}"
|
368
|
+
table_deletes = tables_to_delete.map { |table| +"DELETE FROM #{quote_table_name table}" }
|
389
369
|
total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
|
390
370
|
|
391
371
|
disable_referential_integrity do
|
@@ -398,7 +378,7 @@ module ActiveRecord
|
|
398
378
|
end
|
399
379
|
end
|
400
380
|
|
401
|
-
def empty_insert_statement_value
|
381
|
+
def empty_insert_statement_value(primary_key = nil)
|
402
382
|
"DEFAULT VALUES"
|
403
383
|
end
|
404
384
|
|
@@ -416,16 +396,6 @@ module ActiveRecord
|
|
416
396
|
end
|
417
397
|
end
|
418
398
|
|
419
|
-
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
420
|
-
# on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
|
421
|
-
# an UPDATE statement, so in the MySQL adapters we redefine this to do that.
|
422
|
-
def join_to_update(update, select, key) # :nodoc:
|
423
|
-
subselect = subquery_for(key, select)
|
424
|
-
|
425
|
-
update.where key.in(subselect)
|
426
|
-
end
|
427
|
-
alias join_to_delete join_to_update
|
428
|
-
|
429
399
|
private
|
430
400
|
def default_insert_value(column)
|
431
401
|
Arel.sql("DEFAULT")
|
@@ -466,13 +436,6 @@ module ActiveRecord
|
|
466
436
|
total_sql.join(";\n")
|
467
437
|
end
|
468
438
|
|
469
|
-
# Returns a subquery for the given key using the join information.
|
470
|
-
def subquery_for(key, select)
|
471
|
-
subselect = select.clone
|
472
|
-
subselect.projections = [key]
|
473
|
-
subselect
|
474
|
-
end
|
475
|
-
|
476
439
|
# Returns an ActiveRecord::Result instance.
|
477
440
|
def select(sql, name = nil, binds = [])
|
478
441
|
exec_query(sql, name, binds, prepare: false)
|
@@ -482,7 +445,7 @@ module ActiveRecord
|
|
482
445
|
exec_query(sql, name, binds, prepare: true)
|
483
446
|
end
|
484
447
|
|
485
|
-
def sql_for_insert(sql, pk,
|
448
|
+
def sql_for_insert(sql, pk, sequence_name, binds)
|
486
449
|
[sql, binds]
|
487
450
|
end
|
488
451
|
|
@@ -513,28 +476,6 @@ module ActiveRecord
|
|
513
476
|
value
|
514
477
|
end
|
515
478
|
end
|
516
|
-
|
517
|
-
class PartialQueryCollector
|
518
|
-
def initialize
|
519
|
-
@parts = []
|
520
|
-
@binds = []
|
521
|
-
end
|
522
|
-
|
523
|
-
def <<(str)
|
524
|
-
@parts << str
|
525
|
-
self
|
526
|
-
end
|
527
|
-
|
528
|
-
def add_bind(obj)
|
529
|
-
@binds << obj
|
530
|
-
@parts << Arel::Nodes::BindParam.new(1)
|
531
|
-
self
|
532
|
-
end
|
533
|
-
|
534
|
-
def value
|
535
|
-
[@parts, @binds]
|
536
|
-
end
|
537
|
-
end
|
538
479
|
end
|
539
480
|
end
|
540
481
|
end
|