activerecord 4.2.11.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1282 -1195
- 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.rb +8 -4
- data/lib/active_record/aggregations.rb +35 -24
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations.rb +317 -209
- 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.rb +29 -19
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/preloader.rb +14 -4
- 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/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +76 -47
- 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_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- 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.rb +1 -6
- 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/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.rb +363 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- 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.rb +176 -116
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- 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.rb +120 -107
- 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/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/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.rb +32 -15
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- 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.rb +66 -17
- 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_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- 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/rails/generators/active_record/migration.rb +7 -0
- 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/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 +59 -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
@@ -1,38 +1,57 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
class StatementPool
|
3
|
+
class StatementPool # :nodoc:
|
4
4
|
include Enumerable
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
DEFAULT_STATEMENT_LIMIT = 1000
|
7
|
+
|
8
|
+
def initialize(statement_limit = nil)
|
9
|
+
@cache = Hash.new { |h,pid| h[pid] = {} }
|
10
|
+
@statement_limit = statement_limit || DEFAULT_STATEMENT_LIMIT
|
9
11
|
end
|
10
12
|
|
11
|
-
def each
|
12
|
-
|
13
|
+
def each(&block)
|
14
|
+
cache.each(&block)
|
13
15
|
end
|
14
16
|
|
15
17
|
def key?(key)
|
16
|
-
|
18
|
+
cache.key?(key)
|
17
19
|
end
|
18
20
|
|
19
21
|
def [](key)
|
20
|
-
|
22
|
+
cache[key]
|
21
23
|
end
|
22
24
|
|
23
25
|
def length
|
24
|
-
|
26
|
+
cache.length
|
25
27
|
end
|
26
28
|
|
27
|
-
def []=(sql,
|
28
|
-
|
29
|
+
def []=(sql, stmt)
|
30
|
+
while @statement_limit <= cache.size
|
31
|
+
dealloc(cache.shift.last)
|
32
|
+
end
|
33
|
+
cache[sql] = stmt
|
29
34
|
end
|
30
35
|
|
31
36
|
def clear
|
32
|
-
|
37
|
+
cache.each_value do |stmt|
|
38
|
+
dealloc stmt
|
39
|
+
end
|
40
|
+
cache.clear
|
33
41
|
end
|
34
42
|
|
35
43
|
def delete(key)
|
44
|
+
dealloc cache[key]
|
45
|
+
cache.delete(key)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def cache
|
51
|
+
@cache[Process.pid]
|
52
|
+
end
|
53
|
+
|
54
|
+
def dealloc(stmt)
|
36
55
|
raise NotImplementedError
|
37
56
|
end
|
38
57
|
end
|
@@ -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
|