activerecord 4.2.11.3 → 5.0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1281 -1204
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +35 -24
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +49 -41
- data/lib/active_record/associations/collection_proxy.rb +67 -27
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +13 -37
- data/lib/active_record/attribute_methods.rb +76 -47
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +363 -133
- data/lib/active_record/model_schema.rb +129 -41
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +69 -46
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +79 -108
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +57 -43
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +8 -4
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +60 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -5,10 +5,10 @@ module ActiveRecord
|
|
5
5
|
|
6
6
|
# Establishes the connection to the database. Accepts a hash as input where
|
7
7
|
# the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
|
8
|
-
# example for regular databases (MySQL,
|
8
|
+
# example for regular databases (MySQL, PostgreSQL, etc):
|
9
9
|
#
|
10
10
|
# ActiveRecord::Base.establish_connection(
|
11
|
-
# adapter: "
|
11
|
+
# adapter: "mysql2",
|
12
12
|
# host: "localhost",
|
13
13
|
# username: "myuser",
|
14
14
|
# password: "mypass",
|
@@ -35,26 +35,30 @@ module ActiveRecord
|
|
35
35
|
# "postgres://myuser:mypass@localhost/somedatabase"
|
36
36
|
# )
|
37
37
|
#
|
38
|
-
# In case
|
39
|
-
# automatically loads the contents of config/database.yml into it),
|
38
|
+
# In case {ActiveRecord::Base.configurations}[rdoc-ref:Core.configurations]
|
39
|
+
# is set (Rails automatically loads the contents of config/database.yml into it),
|
40
40
|
# a symbol can also be given as argument, representing a key in the
|
41
41
|
# configuration hash:
|
42
42
|
#
|
43
43
|
# ActiveRecord::Base.establish_connection(:production)
|
44
44
|
#
|
45
|
-
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
45
|
+
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
|
46
46
|
# may be returned on an error.
|
47
47
|
def establish_connection(spec = nil)
|
48
|
+
raise RuntimeError, "Anonymous class is not allowed." unless name
|
49
|
+
|
48
50
|
spec ||= DEFAULT_ENV.call.to_sym
|
49
51
|
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
50
|
-
|
52
|
+
# TODO: uses name on establish_connection, for backwards compatibility
|
53
|
+
spec = resolver.spec(spec, self == Base ? "primary" : name)
|
51
54
|
|
52
55
|
unless respond_to?(spec.adapter_method)
|
53
56
|
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
54
57
|
end
|
55
58
|
|
56
|
-
remove_connection
|
57
|
-
|
59
|
+
remove_connection(spec.name)
|
60
|
+
self.connection_specification_name = spec.name
|
61
|
+
connection_handler.establish_connection spec
|
58
62
|
end
|
59
63
|
|
60
64
|
class MergeAndResolveDefaultUrlConfig # :nodoc:
|
@@ -87,8 +91,19 @@ module ActiveRecord
|
|
87
91
|
retrieve_connection
|
88
92
|
end
|
89
93
|
|
94
|
+
attr_writer :connection_specification_name
|
95
|
+
|
96
|
+
# Return the specification id from this class otherwise look it up
|
97
|
+
# in the parent.
|
98
|
+
def connection_specification_name
|
99
|
+
if !defined?(@connection_specification_name) || @connection_specification_name.nil?
|
100
|
+
return self == Base ? "primary" : superclass.connection_specification_name
|
101
|
+
end
|
102
|
+
@connection_specification_name
|
103
|
+
end
|
104
|
+
|
90
105
|
def connection_id
|
91
|
-
ActiveRecord::RuntimeRegistry.connection_id
|
106
|
+
ActiveRecord::RuntimeRegistry.connection_id ||= Thread.current.object_id
|
92
107
|
end
|
93
108
|
|
94
109
|
def connection_id=(connection_id)
|
@@ -106,20 +121,28 @@ module ActiveRecord
|
|
106
121
|
end
|
107
122
|
|
108
123
|
def connection_pool
|
109
|
-
connection_handler.retrieve_connection_pool(
|
124
|
+
connection_handler.retrieve_connection_pool(connection_specification_name) or raise ConnectionNotEstablished
|
110
125
|
end
|
111
126
|
|
112
127
|
def retrieve_connection
|
113
|
-
connection_handler.retrieve_connection(
|
128
|
+
connection_handler.retrieve_connection(connection_specification_name)
|
114
129
|
end
|
115
130
|
|
116
131
|
# Returns +true+ if Active Record is connected.
|
117
132
|
def connected?
|
118
|
-
connection_handler.connected?(
|
133
|
+
connection_handler.connected?(connection_specification_name)
|
119
134
|
end
|
120
135
|
|
121
|
-
def remove_connection(
|
122
|
-
|
136
|
+
def remove_connection(name = nil)
|
137
|
+
name ||= @connection_specification_name if defined?(@connection_specification_name)
|
138
|
+
# if removing a connection that have a pool, we reset the
|
139
|
+
# connection_specification_name so it will use the parent
|
140
|
+
# pool.
|
141
|
+
if connection_handler.retrieve_connection_pool(name)
|
142
|
+
self.connection_specification_name = nil
|
143
|
+
end
|
144
|
+
|
145
|
+
connection_handler.remove_connection(name)
|
123
146
|
end
|
124
147
|
|
125
148
|
def clear_cache! # :nodoc:
|
data/lib/active_record/core.rb
CHANGED
@@ -70,6 +70,14 @@ module ActiveRecord
|
|
70
70
|
mattr_accessor :schema_format, instance_writer: false
|
71
71
|
self.schema_format = :ruby
|
72
72
|
|
73
|
+
##
|
74
|
+
# :singleton-method:
|
75
|
+
# Specifies if an error should be raised on query limit or order being
|
76
|
+
# ignored when doing batch queries. Useful in applications where the
|
77
|
+
# limit or scope being ignored is error-worthy, rather than a warning.
|
78
|
+
mattr_accessor :error_on_ignored_order_or_limit, instance_writer: false
|
79
|
+
self.error_on_ignored_order_or_limit = false
|
80
|
+
|
73
81
|
##
|
74
82
|
# :singleton-method:
|
75
83
|
# Specify whether or not to use timestamps for migration versions
|
@@ -85,17 +93,30 @@ module ActiveRecord
|
|
85
93
|
mattr_accessor :dump_schema_after_migration, instance_writer: false
|
86
94
|
self.dump_schema_after_migration = true
|
87
95
|
|
96
|
+
##
|
97
|
+
# :singleton-method:
|
98
|
+
# Specifies which database schemas to dump when calling db:structure:dump.
|
99
|
+
# If the value is :schema_search_path (the default), any schemas listed in
|
100
|
+
# schema_search_path are dumped. Use :all to dump all schemas regardless
|
101
|
+
# of schema_search_path, or a string of comma separated schemas for a
|
102
|
+
# custom list.
|
103
|
+
mattr_accessor :dump_schemas, instance_writer: false
|
104
|
+
self.dump_schemas = :schema_search_path
|
105
|
+
|
106
|
+
##
|
107
|
+
# :singleton-method:
|
108
|
+
# Specify a threshold for the size of query result sets. If the number of
|
109
|
+
# records in the set exceeds the threshold, a warning is logged. This can
|
110
|
+
# be used to identify queries which load thousands of records and
|
111
|
+
# potentially cause memory bloat.
|
112
|
+
mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
|
113
|
+
self.warn_on_records_fetched_greater_than = nil
|
114
|
+
|
88
115
|
mattr_accessor :maintain_test_schema, instance_accessor: false
|
89
116
|
|
90
|
-
|
91
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
92
|
-
Implicit join references were removed with Rails 4.1.
|
93
|
-
Make sure to remove this configuration because it does nothing.
|
94
|
-
MSG
|
95
|
-
end
|
117
|
+
mattr_accessor :belongs_to_required_by_default, instance_accessor: false
|
96
118
|
|
97
119
|
class_attribute :default_connection_handler, instance_writer: false
|
98
|
-
class_attribute :find_by_statement_cache
|
99
120
|
|
100
121
|
def self.connection_handler
|
101
122
|
ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
|
@@ -115,10 +136,11 @@ module ActiveRecord
|
|
115
136
|
end
|
116
137
|
|
117
138
|
def initialize_find_by_cache # :nodoc:
|
118
|
-
|
139
|
+
@find_by_statement_cache = { true => {}.extend(Mutex_m), false => {}.extend(Mutex_m) }
|
119
140
|
end
|
120
141
|
|
121
142
|
def inherited(child_class) # :nodoc:
|
143
|
+
# initialize cache at class definition for thread safety
|
122
144
|
child_class.initialize_find_by_cache
|
123
145
|
super
|
124
146
|
end
|
@@ -126,12 +148,9 @@ module ActiveRecord
|
|
126
148
|
def find(*ids) # :nodoc:
|
127
149
|
# We don't have cache keys for this stuff yet
|
128
150
|
return super unless ids.length == 1
|
129
|
-
# Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
|
130
|
-
return super if ids.first.kind_of?(Symbol)
|
131
151
|
return super if block_given? ||
|
132
152
|
primary_key.nil? ||
|
133
|
-
|
134
|
-
current_scope ||
|
153
|
+
scope_attributes? ||
|
135
154
|
columns_hash.include?(inheritance_column) ||
|
136
155
|
ids.first.kind_of?(Array)
|
137
156
|
|
@@ -140,60 +159,57 @@ module ActiveRecord
|
|
140
159
|
id = id.id
|
141
160
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
142
161
|
You are passing an instance of ActiveRecord::Base to `find`.
|
143
|
-
Please pass the id of the object by calling `.id
|
162
|
+
Please pass the id of the object by calling `.id`.
|
144
163
|
MSG
|
145
164
|
end
|
165
|
+
|
146
166
|
key = primary_key
|
147
167
|
|
148
|
-
|
149
|
-
|
150
|
-
where(key => params.bind).limit(1)
|
151
|
-
}
|
168
|
+
statement = cached_find_by_statement(key) { |params|
|
169
|
+
where(key => params.bind).limit(1)
|
152
170
|
}
|
153
|
-
record =
|
171
|
+
record = statement.execute([id], self, connection).first
|
154
172
|
unless record
|
155
|
-
raise RecordNotFound
|
173
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
|
174
|
+
name, primary_key, id)
|
156
175
|
end
|
157
176
|
record
|
158
177
|
rescue RangeError
|
159
|
-
raise RecordNotFound
|
178
|
+
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
179
|
+
name, primary_key)
|
160
180
|
end
|
161
181
|
|
162
182
|
def find_by(*args) # :nodoc:
|
163
|
-
return super if
|
164
|
-
return super if default_scopes.any?
|
183
|
+
return super if scope_attributes? || !(Hash === args.first) || reflect_on_all_aggregations.any?
|
165
184
|
|
166
185
|
hash = args.first
|
167
186
|
|
168
187
|
return super if hash.values.any? { |v|
|
169
|
-
v.nil? || Array === v || Hash === v
|
188
|
+
v.nil? || Array === v || Hash === v || Relation === v
|
170
189
|
}
|
171
190
|
|
172
191
|
# We can't cache Post.find_by(author: david) ...yet
|
173
192
|
return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
|
174
193
|
|
175
|
-
|
194
|
+
keys = hash.keys
|
176
195
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
wheres = key.each_with_object({}) { |param,o|
|
181
|
-
o[param] = params.bind
|
182
|
-
}
|
183
|
-
klass.where(wheres).limit(1)
|
196
|
+
statement = cached_find_by_statement(keys) { |params|
|
197
|
+
wheres = keys.each_with_object({}) { |param, o|
|
198
|
+
o[param] = params.bind
|
184
199
|
}
|
200
|
+
where(wheres).limit(1)
|
185
201
|
}
|
186
202
|
begin
|
187
|
-
|
188
|
-
rescue TypeError
|
189
|
-
raise ActiveRecord::StatementInvalid
|
203
|
+
statement.execute(hash.values, self, connection).first
|
204
|
+
rescue TypeError
|
205
|
+
raise ActiveRecord::StatementInvalid
|
190
206
|
rescue RangeError
|
191
207
|
nil
|
192
208
|
end
|
193
209
|
end
|
194
210
|
|
195
211
|
def find_by!(*args) # :nodoc:
|
196
|
-
find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
|
212
|
+
find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}", name)
|
197
213
|
end
|
198
214
|
|
199
215
|
def initialize_generated_modules # :nodoc:
|
@@ -217,7 +233,7 @@ module ActiveRecord
|
|
217
233
|
elsif !connected?
|
218
234
|
"#{super} (call '#{super}.connection' to establish a connection)"
|
219
235
|
elsif table_exists?
|
220
|
-
attr_list =
|
236
|
+
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ', '
|
221
237
|
"#{super}(#{attr_list})"
|
222
238
|
else
|
223
239
|
"#{super}(Table doesn't exist)"
|
@@ -235,30 +251,54 @@ module ActiveRecord
|
|
235
251
|
# scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
|
236
252
|
# end
|
237
253
|
def arel_table # :nodoc:
|
238
|
-
@arel_table ||= Arel::Table.new(table_name,
|
254
|
+
@arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
|
239
255
|
end
|
240
256
|
|
241
257
|
# Returns the Arel engine.
|
242
258
|
def arel_engine # :nodoc:
|
243
259
|
@arel_engine ||=
|
244
|
-
if Base == self || connection_handler.retrieve_connection_pool(
|
260
|
+
if Base == self || connection_handler.retrieve_connection_pool(connection_specification_name)
|
245
261
|
self
|
246
262
|
else
|
247
263
|
superclass.arel_engine
|
248
264
|
end
|
249
265
|
end
|
250
266
|
|
267
|
+
def arel_attribute(name, table = arel_table) # :nodoc:
|
268
|
+
name = attribute_alias(name) if attribute_alias?(name)
|
269
|
+
table[name]
|
270
|
+
end
|
271
|
+
|
272
|
+
def predicate_builder # :nodoc:
|
273
|
+
@predicate_builder ||= PredicateBuilder.new(table_metadata)
|
274
|
+
end
|
275
|
+
|
276
|
+
def type_caster # :nodoc:
|
277
|
+
TypeCaster::Map.new(self)
|
278
|
+
end
|
279
|
+
|
251
280
|
private
|
252
281
|
|
253
|
-
def
|
254
|
-
|
282
|
+
def cached_find_by_statement(key, &block) # :nodoc:
|
283
|
+
cache = @find_by_statement_cache[connection.prepared_statements]
|
284
|
+
cache[key] || cache.synchronize {
|
285
|
+
cache[key] ||= StatementCache.create(connection, &block)
|
286
|
+
}
|
287
|
+
end
|
288
|
+
|
289
|
+
def relation # :nodoc:
|
290
|
+
relation = Relation.create(self, arel_table, predicate_builder)
|
255
291
|
|
256
|
-
if finder_needs_type_condition?
|
292
|
+
if finder_needs_type_condition? && !ignore_default_scope?
|
257
293
|
relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
|
258
294
|
else
|
259
295
|
relation
|
260
296
|
end
|
261
297
|
end
|
298
|
+
|
299
|
+
def table_metadata # :nodoc:
|
300
|
+
TableMetadata.new(self, arel_table)
|
301
|
+
end
|
262
302
|
end
|
263
303
|
|
264
304
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
@@ -269,16 +309,14 @@ module ActiveRecord
|
|
269
309
|
# ==== Example:
|
270
310
|
# # Instantiates a single new object
|
271
311
|
# User.new(first_name: 'Jamie')
|
272
|
-
def initialize(attributes = nil
|
273
|
-
@attributes = self.class._default_attributes.
|
312
|
+
def initialize(attributes = nil)
|
313
|
+
@attributes = self.class._default_attributes.deep_dup
|
274
314
|
self.class.define_attribute_methods
|
275
315
|
|
276
316
|
init_internals
|
277
317
|
initialize_internals_callback
|
278
318
|
|
279
|
-
|
280
|
-
# Remove it when we drop support to this gem.
|
281
|
-
init_attributes(attributes, options) if attributes
|
319
|
+
assign_attributes(attributes) if attributes
|
282
320
|
|
283
321
|
yield self if block_given?
|
284
322
|
_run_initialize_callbacks
|
@@ -286,7 +324,7 @@ module ActiveRecord
|
|
286
324
|
|
287
325
|
# Initialize an empty model object from +coder+. +coder+ should be
|
288
326
|
# the result of previously encoding an Active Record model, using
|
289
|
-
#
|
327
|
+
# #encode_with.
|
290
328
|
#
|
291
329
|
# class Post < ActiveRecord::Base
|
292
330
|
# end
|
@@ -342,14 +380,11 @@ module ActiveRecord
|
|
342
380
|
|
343
381
|
##
|
344
382
|
def initialize_dup(other) # :nodoc:
|
345
|
-
@attributes = @attributes.
|
383
|
+
@attributes = @attributes.deep_dup
|
346
384
|
@attributes.reset(self.class.primary_key)
|
347
385
|
|
348
386
|
_run_initialize_callbacks
|
349
387
|
|
350
|
-
@aggregation_cache = {}
|
351
|
-
@association_cache = {}
|
352
|
-
|
353
388
|
@new_record = true
|
354
389
|
@destroyed = false
|
355
390
|
|
@@ -358,7 +393,7 @@ module ActiveRecord
|
|
358
393
|
|
359
394
|
# Populate +coder+ with attributes about this record that should be
|
360
395
|
# serialized. The structure of +coder+ defined in this method is
|
361
|
-
# guaranteed to match the structure of +coder+ passed to the
|
396
|
+
# guaranteed to match the structure of +coder+ passed to the #init_with
|
362
397
|
# method.
|
363
398
|
#
|
364
399
|
# Example:
|
@@ -373,7 +408,7 @@ module ActiveRecord
|
|
373
408
|
coder['raw_attributes'] = attributes_before_type_cast
|
374
409
|
coder['attributes'] = @attributes
|
375
410
|
coder['new_record'] = new_record?
|
376
|
-
coder['active_record_yaml_version'] =
|
411
|
+
coder['active_record_yaml_version'] = 1
|
377
412
|
end
|
378
413
|
|
379
414
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -456,7 +491,7 @@ module ActiveRecord
|
|
456
491
|
"#<#{self.class} #{inspection}>"
|
457
492
|
end
|
458
493
|
|
459
|
-
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from
|
494
|
+
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
460
495
|
# when pp is required.
|
461
496
|
def pretty_print(pp)
|
462
497
|
return super if custom_inspect_method_defined?
|
@@ -487,51 +522,6 @@ module ActiveRecord
|
|
487
522
|
|
488
523
|
private
|
489
524
|
|
490
|
-
def set_transaction_state(state) # :nodoc:
|
491
|
-
@transaction_state = state
|
492
|
-
end
|
493
|
-
|
494
|
-
def has_transactional_callbacks? # :nodoc:
|
495
|
-
!_rollback_callbacks.empty? || !_commit_callbacks.empty?
|
496
|
-
end
|
497
|
-
|
498
|
-
# Updates the attributes on this particular ActiveRecord object so that
|
499
|
-
# if it is associated with a transaction, then the state of the AR object
|
500
|
-
# will be updated to reflect the current state of the transaction
|
501
|
-
#
|
502
|
-
# The @transaction_state variable stores the states of the associated
|
503
|
-
# transaction. This relies on the fact that a transaction can only be in
|
504
|
-
# one rollback or commit (otherwise a list of states would be required)
|
505
|
-
# Each AR object inside of a transaction carries that transaction's
|
506
|
-
# TransactionState.
|
507
|
-
#
|
508
|
-
# This method checks to see if the ActiveRecord object's state reflects
|
509
|
-
# the TransactionState, and rolls back or commits the ActiveRecord object
|
510
|
-
# as appropriate.
|
511
|
-
#
|
512
|
-
# Since ActiveRecord objects can be inside multiple transactions, this
|
513
|
-
# method recursively goes through the parent of the TransactionState and
|
514
|
-
# checks if the ActiveRecord object reflects the state of the object.
|
515
|
-
def sync_with_transaction_state
|
516
|
-
update_attributes_from_transaction_state(@transaction_state, 0)
|
517
|
-
end
|
518
|
-
|
519
|
-
def update_attributes_from_transaction_state(transaction_state, depth)
|
520
|
-
@reflects_state = [false] if depth == 0
|
521
|
-
|
522
|
-
if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
|
523
|
-
unless @reflects_state[depth]
|
524
|
-
restore_transaction_record_state if transaction_state.rolledback?
|
525
|
-
clear_transaction_record_state
|
526
|
-
@reflects_state[depth] = true
|
527
|
-
end
|
528
|
-
|
529
|
-
if transaction_state.parent && !@reflects_state[depth+1]
|
530
|
-
update_attributes_from_transaction_state(transaction_state.parent, depth+1)
|
531
|
-
end
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
525
|
# Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
|
536
526
|
# of the array, and then rescues from the possible NoMethodError. If those elements are
|
537
527
|
# ActiveRecord::Base's, then this triggers the various method_missing's that we have,
|
@@ -545,8 +535,6 @@ module ActiveRecord
|
|
545
535
|
end
|
546
536
|
|
547
537
|
def init_internals
|
548
|
-
@aggregation_cache = {}
|
549
|
-
@association_cache = {}
|
550
538
|
@readonly = false
|
551
539
|
@destroyed = false
|
552
540
|
@marked_for_destruction = false
|
@@ -560,12 +548,6 @@ module ActiveRecord
|
|
560
548
|
def initialize_internals_callback
|
561
549
|
end
|
562
550
|
|
563
|
-
# This method is needed to make protected_attributes gem easier to hook.
|
564
|
-
# Remove it when we drop support to this gem.
|
565
|
-
def init_attributes(attributes, options)
|
566
|
-
assign_attributes(attributes)
|
567
|
-
end
|
568
|
-
|
569
551
|
def thaw
|
570
552
|
if frozen?
|
571
553
|
@attributes = @attributes.dup
|
@@ -37,23 +37,22 @@ module ActiveRecord
|
|
37
37
|
reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
38
38
|
counter_name = reflection.counter_cache_column
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
connection.update stmt
|
40
|
+
unscoped.where(primary_key => object.id).update_all(
|
41
|
+
counter_name => object.send(counter_association).count(:all)
|
42
|
+
)
|
44
43
|
end
|
45
44
|
return true
|
46
45
|
end
|
47
46
|
|
48
47
|
# A generic "counter updater" implementation, intended primarily to be
|
49
|
-
# used by increment_counter and decrement_counter, but which may also
|
48
|
+
# used by #increment_counter and #decrement_counter, but which may also
|
50
49
|
# be useful on its own. It simply does a direct SQL update for the record
|
51
50
|
# with the given ID, altering the given hash of counters by the amount
|
52
51
|
# given by the corresponding value:
|
53
52
|
#
|
54
53
|
# ==== Parameters
|
55
54
|
#
|
56
|
-
# * +id+ - The id of the object you wish to update a counter on or an
|
55
|
+
# * +id+ - The id of the object you wish to update a counter on or an array of ids.
|
57
56
|
# * +counters+ - A Hash containing the names of the fields
|
58
57
|
# to update as keys and the amount to update the field by as values.
|
59
58
|
#
|
@@ -87,52 +86,42 @@ module ActiveRecord
|
|
87
86
|
# Increment a numeric field by one, via a direct SQL update.
|
88
87
|
#
|
89
88
|
# This method is used primarily for maintaining counter_cache columns that are
|
90
|
-
# used to store aggregate values. For example, a DiscussionBoard may cache
|
89
|
+
# used to store aggregate values. For example, a +DiscussionBoard+ may cache
|
91
90
|
# posts_count and comments_count to avoid running an SQL query to calculate the
|
92
91
|
# number of posts and comments there are, each time it is displayed.
|
93
92
|
#
|
94
93
|
# ==== Parameters
|
95
94
|
#
|
96
95
|
# * +counter_name+ - The name of the field that should be incremented.
|
97
|
-
# * +id+ - The id of the object that should be incremented or an
|
96
|
+
# * +id+ - The id of the object that should be incremented or an array of ids.
|
98
97
|
#
|
99
98
|
# ==== Examples
|
100
99
|
#
|
101
|
-
# # Increment the
|
102
|
-
# DiscussionBoard.increment_counter(:
|
100
|
+
# # Increment the posts_count column for the record with an id of 5
|
101
|
+
# DiscussionBoard.increment_counter(:posts_count, 5)
|
103
102
|
def increment_counter(counter_name, id)
|
104
103
|
update_counters(id, counter_name => 1)
|
105
104
|
end
|
106
105
|
|
107
106
|
# Decrement a numeric field by one, via a direct SQL update.
|
108
107
|
#
|
109
|
-
# This works the same as increment_counter but reduces the column value by
|
108
|
+
# This works the same as #increment_counter but reduces the column value by
|
110
109
|
# 1 instead of increasing it.
|
111
110
|
#
|
112
111
|
# ==== Parameters
|
113
112
|
#
|
114
113
|
# * +counter_name+ - The name of the field that should be decremented.
|
115
|
-
# * +id+ - The id of the object that should be decremented or an
|
114
|
+
# * +id+ - The id of the object that should be decremented or an array of ids.
|
116
115
|
#
|
117
116
|
# ==== Examples
|
118
117
|
#
|
119
|
-
# # Decrement the
|
120
|
-
# DiscussionBoard.decrement_counter(:
|
118
|
+
# # Decrement the posts_count column for the record with an id of 5
|
119
|
+
# DiscussionBoard.decrement_counter(:posts_count, 5)
|
121
120
|
def decrement_counter(counter_name, id)
|
122
121
|
update_counters(id, counter_name => -1)
|
123
122
|
end
|
124
123
|
end
|
125
124
|
|
126
|
-
protected
|
127
|
-
|
128
|
-
def actually_destroyed?
|
129
|
-
@_actually_destroyed
|
130
|
-
end
|
131
|
-
|
132
|
-
def clear_destroy_state
|
133
|
-
@_actually_destroyed = nil
|
134
|
-
end
|
135
|
-
|
136
125
|
private
|
137
126
|
|
138
127
|
def _create_record(*)
|
@@ -1,10 +1,5 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module DynamicMatchers #:nodoc:
|
3
|
-
# This code in this file seems to have a lot of indirection, but the indirection
|
4
|
-
# is there to provide extension points for the activerecord-deprecated_finders
|
5
|
-
# gem. When we stop supporting activerecord-deprecated_finders (from Rails 5),
|
6
|
-
# then we can remove the indirection.
|
7
|
-
|
8
3
|
def respond_to?(name, include_private = false)
|
9
4
|
if self == Base
|
10
5
|
super
|
@@ -72,26 +67,14 @@ module ActiveRecord
|
|
72
67
|
CODE
|
73
68
|
end
|
74
69
|
|
75
|
-
|
76
|
-
raise NotImplementedError
|
77
|
-
end
|
78
|
-
end
|
70
|
+
private
|
79
71
|
|
80
|
-
module Finder
|
81
|
-
# Extended in activerecord-deprecated_finders
|
82
72
|
def body
|
83
|
-
result
|
84
|
-
end
|
85
|
-
|
86
|
-
# Extended in activerecord-deprecated_finders
|
87
|
-
def result
|
88
73
|
"#{finder}(#{attributes_hash})"
|
89
74
|
end
|
90
75
|
|
91
76
|
# The parameters in the signature may have reserved Ruby words, in order
|
92
77
|
# to prevent errors, we start each param name with `_`.
|
93
|
-
#
|
94
|
-
# Extended in activerecord-deprecated_finders
|
95
78
|
def signature
|
96
79
|
attribute_names.map { |name| "_#{name}" }.join(', ')
|
97
80
|
end
|
@@ -109,7 +92,6 @@ module ActiveRecord
|
|
109
92
|
|
110
93
|
class FindBy < Method
|
111
94
|
Method.matchers << self
|
112
|
-
include Finder
|
113
95
|
|
114
96
|
def self.prefix
|
115
97
|
"find_by"
|
@@ -122,7 +104,6 @@ module ActiveRecord
|
|
122
104
|
|
123
105
|
class FindByBang < Method
|
124
106
|
Method.matchers << self
|
125
|
-
include Finder
|
126
107
|
|
127
108
|
def self.prefix
|
128
109
|
"find_by"
|