activerecord 4.2.6 → 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 +4 -4
- data/CHANGELOG.md +1307 -1105
- 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 +37 -23
- 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 +50 -31
- data/lib/active_record/associations/collection_proxy.rb +69 -29
- 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 +20 -8
- 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 +20 -141
- 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 +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- 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 -80
- 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 -9
- 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 +378 -140
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
- 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 +25 -176
- 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 -56
- 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 +148 -203
- 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 +3 -3
- 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 +364 -109
- data/lib/active_record/model_schema.rb +128 -38
- 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 +27 -18
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +58 -45
- 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 +80 -102
- 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 -15
- 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 -17
- 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 +58 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
- 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 -41
- 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 +7 -2
- 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 +58 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- 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 -50
- 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 -105
data/lib/active_record/base.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'set'
|
3
2
|
require 'active_support/benchmarkable'
|
4
3
|
require 'active_support/dependencies'
|
5
4
|
require 'active_support/descendants_tracker'
|
6
5
|
require 'active_support/time'
|
7
6
|
require 'active_support/core_ext/module/attribute_accessors'
|
8
|
-
require 'active_support/core_ext/class/delegating_attributes'
|
9
7
|
require 'active_support/core_ext/array/extract_options'
|
10
8
|
require 'active_support/core_ext/hash/deep_merge'
|
11
9
|
require 'active_support/core_ext/hash/slice'
|
@@ -15,13 +13,13 @@ require 'active_support/core_ext/kernel/singleton_class'
|
|
15
13
|
require 'active_support/core_ext/module/introspection'
|
16
14
|
require 'active_support/core_ext/object/duplicable'
|
17
15
|
require 'active_support/core_ext/class/subclasses'
|
18
|
-
require 'arel'
|
19
16
|
require 'active_record/attribute_decorators'
|
20
17
|
require 'active_record/errors'
|
21
18
|
require 'active_record/log_subscriber'
|
22
19
|
require 'active_record/explain_subscriber'
|
23
20
|
require 'active_record/relation/delegation'
|
24
21
|
require 'active_record/attributes'
|
22
|
+
require 'active_record/type_caster'
|
25
23
|
|
26
24
|
module ActiveRecord #:nodoc:
|
27
25
|
# = Active Record
|
@@ -133,14 +131,11 @@ module ActiveRecord #:nodoc:
|
|
133
131
|
# end
|
134
132
|
# end
|
135
133
|
#
|
136
|
-
# You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
|
137
|
-
# or <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
|
138
|
-
#
|
139
134
|
# == Attribute query methods
|
140
135
|
#
|
141
136
|
# In addition to the basic accessors, query methods are also automatically available on the Active Record object.
|
142
137
|
# Query methods allow you to test whether an attribute value is present.
|
143
|
-
#
|
138
|
+
# Additionally, when dealing with numeric values, a query method will return false if the value is zero.
|
144
139
|
#
|
145
140
|
# For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
|
146
141
|
# to determine whether the user has a name:
|
@@ -171,10 +166,11 @@ module ActiveRecord #:nodoc:
|
|
171
166
|
# <tt>Person.find_by_user_name(user_name)</tt>.
|
172
167
|
#
|
173
168
|
# It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
|
174
|
-
#
|
169
|
+
# ActiveRecord::RecordNotFound error if they do not return any records,
|
175
170
|
# like <tt>Person.find_by_last_name!</tt>.
|
176
171
|
#
|
177
|
-
# It's also possible to use multiple attributes in the same
|
172
|
+
# It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
|
173
|
+
# "_and_".
|
178
174
|
#
|
179
175
|
# Person.find_by(user_name: user_name, password: password)
|
180
176
|
# Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
|
@@ -186,7 +182,8 @@ module ActiveRecord #:nodoc:
|
|
186
182
|
# == Saving arrays, hashes, and other non-mappable objects in text columns
|
187
183
|
#
|
188
184
|
# Active Record can serialize any object in text columns using YAML. To do so, you must
|
189
|
-
# specify this with a call to the class method
|
185
|
+
# specify this with a call to the class method
|
186
|
+
# {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
|
190
187
|
# This makes it possible to store arrays, hashes, and other non-mappable objects without doing
|
191
188
|
# any additional work.
|
192
189
|
#
|
@@ -226,39 +223,47 @@ module ActiveRecord #:nodoc:
|
|
226
223
|
#
|
227
224
|
# == Connection to multiple databases in different models
|
228
225
|
#
|
229
|
-
# Connections are usually created through
|
226
|
+
# Connections are usually created through
|
227
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
|
230
228
|
# by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
|
231
229
|
# connection. But you can also set a class-specific connection. For example, if Course is an
|
232
230
|
# ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
|
233
231
|
# and Course and all of its subclasses will use this connection instead.
|
234
232
|
#
|
235
233
|
# This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
|
236
|
-
# a
|
234
|
+
# a hash indexed by the class. If a connection is requested, the
|
235
|
+
# {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
|
237
236
|
# will go up the class-hierarchy until a connection is found in the connection pool.
|
238
237
|
#
|
239
238
|
# == Exceptions
|
240
239
|
#
|
241
240
|
# * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
|
242
|
-
# * AdapterNotSpecified - The configuration hash used in
|
243
|
-
#
|
244
|
-
#
|
245
|
-
#
|
241
|
+
# * AdapterNotSpecified - The configuration hash used in
|
242
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
243
|
+
# didn't include an <tt>:adapter</tt> key.
|
244
|
+
# * AdapterNotFound - The <tt>:adapter</tt> key used in
|
245
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
246
|
+
# specified a non-existent adapter
|
246
247
|
# (or a bad spelling of an existing one).
|
247
248
|
# * AssociationTypeMismatch - The object assigned to the association wasn't of the type
|
248
249
|
# specified in the association definition.
|
249
250
|
# * AttributeAssignmentError - An error occurred while doing a mass assignment through the
|
250
|
-
#
|
251
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
251
252
|
# You can inspect the +attribute+ property of the exception object to determine which attribute
|
252
253
|
# triggered the error.
|
253
|
-
# * ConnectionNotEstablished - No connection has been established.
|
254
|
-
# before querying.
|
254
|
+
# * ConnectionNotEstablished - No connection has been established.
|
255
|
+
# Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
|
255
256
|
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
|
256
|
-
#
|
257
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
258
|
+
# The +errors+ property of this exception contains an array of
|
257
259
|
# AttributeAssignmentError
|
258
260
|
# objects that should be inspected to determine which attributes triggered the errors.
|
259
|
-
# * RecordInvalid - raised by save! and
|
260
|
-
#
|
261
|
-
#
|
261
|
+
# * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
262
|
+
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
|
263
|
+
# when the record is invalid.
|
264
|
+
# * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
|
265
|
+
# Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
|
266
|
+
# Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
|
262
267
|
# nothing was found, please check its documentation for further details.
|
263
268
|
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
|
264
269
|
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
|
@@ -280,6 +285,7 @@ module ActiveRecord #:nodoc:
|
|
280
285
|
extend Explain
|
281
286
|
extend Enum
|
282
287
|
extend Delegation::DelegateCache
|
288
|
+
extend CollectionCacheKey
|
283
289
|
|
284
290
|
include Core
|
285
291
|
include Persistence
|
@@ -307,9 +313,12 @@ module ActiveRecord #:nodoc:
|
|
307
313
|
include Aggregations
|
308
314
|
include Transactions
|
309
315
|
include NoTouching
|
316
|
+
include TouchLater
|
310
317
|
include Reflection
|
311
318
|
include Serialization
|
312
319
|
include Store
|
320
|
+
include SecureToken
|
321
|
+
include Suppressor
|
313
322
|
end
|
314
323
|
|
315
324
|
ActiveSupport.run_load_hooks(:active_record, Base)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
# = Active Record Callbacks
|
2
|
+
# = Active Record \Callbacks
|
3
3
|
#
|
4
|
-
# Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
|
4
|
+
# \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
|
5
5
|
# before or after an alteration of the object state. This can be used to make sure that associated and
|
6
|
-
# dependent objects are deleted when
|
7
|
-
# before they're validated (by overwriting +before_validation+).
|
8
|
-
# the
|
6
|
+
# dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
|
7
|
+
# to massage attributes before they're validated (by overwriting +before_validation+).
|
8
|
+
# As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
|
9
9
|
#
|
10
10
|
# * (-) <tt>save</tt>
|
11
11
|
# * (-) <tt>valid</tt>
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
# * (7) <tt>after_commit</tt>
|
21
21
|
#
|
22
22
|
# Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
|
23
|
-
# Check out
|
23
|
+
# Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
|
24
24
|
# <tt>after_rollback</tt>.
|
25
25
|
#
|
26
26
|
# Additionally, an <tt>after_touch</tt> callback is triggered whenever an
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
# are instantiated as well.
|
32
32
|
#
|
33
33
|
# There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
|
34
|
-
# Active Record life cycle. The sequence for calling
|
34
|
+
# Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
|
35
35
|
# except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
|
36
36
|
#
|
37
37
|
# Examples:
|
@@ -53,9 +53,9 @@ module ActiveRecord
|
|
53
53
|
# end
|
54
54
|
#
|
55
55
|
# class Firm < ActiveRecord::Base
|
56
|
-
# #
|
57
|
-
# before_destroy { |record| Person.
|
58
|
-
# before_destroy { |record| Client.
|
56
|
+
# # Disables access to the system, for associated clients and people when the firm is destroyed
|
57
|
+
# before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled') }
|
58
|
+
# before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
|
59
59
|
# end
|
60
60
|
#
|
61
61
|
# == Inheritable callback queues
|
@@ -175,43 +175,30 @@ module ActiveRecord
|
|
175
175
|
# end
|
176
176
|
# end
|
177
177
|
#
|
178
|
-
# The callback macros usually accept a symbol for the method they're supposed to run, but you can also
|
179
|
-
# pass a "method string", which will then be evaluated within the binding of the callback. Example:
|
180
|
-
#
|
181
|
-
# class Topic < ActiveRecord::Base
|
182
|
-
# before_destroy 'self.class.delete_all "parent_id = #{id}"'
|
183
|
-
# end
|
184
|
-
#
|
185
|
-
# Notice that single quotes (') are used so the <tt>#{id}</tt> part isn't evaluated until the callback
|
186
|
-
# is triggered. Also note that these inline callbacks can be stacked just like the regular ones:
|
187
|
-
#
|
188
|
-
# class Topic < ActiveRecord::Base
|
189
|
-
# before_destroy 'self.class.delete_all "parent_id = #{id}"',
|
190
|
-
# 'puts "Evaluated after parents are destroyed"'
|
191
|
-
# end
|
192
|
-
#
|
193
178
|
# == <tt>before_validation*</tt> returning statements
|
194
179
|
#
|
195
|
-
# If the
|
196
|
-
# aborted and
|
197
|
-
# ActiveRecord::
|
180
|
+
# If the +before_validation+ callback throws +:abort+, the process will be
|
181
|
+
# aborted and {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will return +false+.
|
182
|
+
# If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] is called it will raise an ActiveRecord::RecordInvalid exception.
|
183
|
+
# Nothing will be appended to the errors object.
|
198
184
|
#
|
199
185
|
# == Canceling callbacks
|
200
186
|
#
|
201
|
-
# If a <tt>before_*</tt> callback
|
202
|
-
# cancelled.
|
187
|
+
# If a <tt>before_*</tt> callback throws +:abort+, all the later callbacks and
|
188
|
+
# the associated action are cancelled.
|
203
189
|
# Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
|
204
190
|
# methods on the model, which are called last.
|
205
191
|
#
|
206
192
|
# == Ordering callbacks
|
207
193
|
#
|
208
194
|
# Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
|
209
|
-
# callback (+log_children+ in this case) should be executed before the children get destroyed by the
|
195
|
+
# callback (+log_children+ in this case) should be executed before the children get destroyed by the
|
196
|
+
# <tt>dependent: :destroy</tt> option.
|
210
197
|
#
|
211
198
|
# Let's look at the code below:
|
212
199
|
#
|
213
200
|
# class Topic < ActiveRecord::Base
|
214
|
-
# has_many :children, dependent: destroy
|
201
|
+
# has_many :children, dependent: :destroy
|
215
202
|
#
|
216
203
|
# before_destroy :log_children
|
217
204
|
#
|
@@ -222,10 +209,11 @@ module ActiveRecord
|
|
222
209
|
# end
|
223
210
|
#
|
224
211
|
# In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
|
225
|
-
# because the
|
212
|
+
# because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
|
213
|
+
# You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
|
226
214
|
#
|
227
215
|
# class Topic < ActiveRecord::Base
|
228
|
-
# has_many :children, dependent: destroy
|
216
|
+
# has_many :children, dependent: :destroy
|
229
217
|
#
|
230
218
|
# before_destroy :log_children, prepend: true
|
231
219
|
#
|
@@ -235,23 +223,23 @@ module ActiveRecord
|
|
235
223
|
# end
|
236
224
|
# end
|
237
225
|
#
|
238
|
-
# This way, the +before_destroy+ gets executed before the <tt>dependent: destroy</tt> is called, and the data is still available.
|
226
|
+
# This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
|
239
227
|
#
|
240
|
-
# == Transactions
|
228
|
+
# == \Transactions
|
241
229
|
#
|
242
|
-
# The entire callback chain of a
|
243
|
-
# within a transaction. That includes <tt>after_*</tt> hooks.
|
244
|
-
# goes fine a COMMIT is executed once the chain has been completed.
|
230
|
+
# The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
|
231
|
+
# or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
|
232
|
+
# If everything goes fine a COMMIT is executed once the chain has been completed.
|
245
233
|
#
|
246
234
|
# If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
|
247
235
|
# can also trigger a ROLLBACK raising an exception in any of the callbacks,
|
248
236
|
# including <tt>after_*</tt> hooks. Note, however, that in that case the client
|
249
|
-
# needs to be aware of it because an ordinary
|
237
|
+
# needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
|
250
238
|
# instead of quietly returning +false+.
|
251
239
|
#
|
252
240
|
# == Debugging callbacks
|
253
241
|
#
|
254
|
-
# The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object.
|
242
|
+
# The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
|
255
243
|
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
|
256
244
|
# defines what part of the chain the callback runs in.
|
257
245
|
#
|
@@ -277,7 +265,7 @@ module ActiveRecord
|
|
277
265
|
:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
|
278
266
|
]
|
279
267
|
|
280
|
-
module ClassMethods
|
268
|
+
module ClassMethods # :nodoc:
|
281
269
|
include ActiveModel::Callbacks
|
282
270
|
end
|
283
271
|
|
@@ -289,7 +277,15 @@ module ActiveRecord
|
|
289
277
|
end
|
290
278
|
|
291
279
|
def destroy #:nodoc:
|
280
|
+
@_destroy_callback_already_called ||= false
|
281
|
+
return if @_destroy_callback_already_called
|
282
|
+
@_destroy_callback_already_called = true
|
292
283
|
_run_destroy_callbacks { super }
|
284
|
+
rescue RecordNotDestroyed => e
|
285
|
+
@_association_destroy_exception = e
|
286
|
+
false
|
287
|
+
ensure
|
288
|
+
@_destroy_callback_already_called = false
|
293
289
|
end
|
294
290
|
|
295
291
|
def touch(*) #:nodoc:
|
@@ -298,7 +294,7 @@ module ActiveRecord
|
|
298
294
|
|
299
295
|
private
|
300
296
|
|
301
|
-
def create_or_update #:nodoc:
|
297
|
+
def create_or_update(*) #:nodoc:
|
302
298
|
_run_save_callbacks { super }
|
303
299
|
end
|
304
300
|
|
@@ -8,15 +8,13 @@ module ActiveRecord
|
|
8
8
|
|
9
9
|
def initialize(object_class = Object)
|
10
10
|
@object_class = object_class
|
11
|
+
check_arity_of_constructor
|
11
12
|
end
|
12
13
|
|
13
14
|
def dump(obj)
|
14
15
|
return if obj.nil?
|
15
16
|
|
16
|
-
|
17
|
-
raise SerializationTypeMismatch,
|
18
|
-
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
|
19
|
-
end
|
17
|
+
assert_valid_value(obj)
|
20
18
|
YAML.dump obj
|
21
19
|
end
|
22
20
|
|
@@ -25,14 +23,28 @@ module ActiveRecord
|
|
25
23
|
return yaml unless yaml.is_a?(String) && yaml =~ /^---/
|
26
24
|
obj = YAML.load(yaml)
|
27
25
|
|
28
|
-
|
29
|
-
raise SerializationTypeMismatch,
|
30
|
-
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
|
31
|
-
end
|
26
|
+
assert_valid_value(obj)
|
32
27
|
obj ||= object_class.new if object_class != Object
|
33
28
|
|
34
29
|
obj
|
35
30
|
end
|
31
|
+
|
32
|
+
def assert_valid_value(obj)
|
33
|
+
unless obj.nil? || obj.is_a?(object_class)
|
34
|
+
raise SerializationTypeMismatch,
|
35
|
+
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def check_arity_of_constructor
|
42
|
+
begin
|
43
|
+
load(nil)
|
44
|
+
rescue ArgumentError
|
45
|
+
raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
|
46
|
+
end
|
47
|
+
end
|
36
48
|
end
|
37
49
|
end
|
38
50
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module CollectionCacheKey
|
3
|
+
|
4
|
+
def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
|
5
|
+
query_signature = Digest::MD5.hexdigest(collection.to_sql)
|
6
|
+
key = "#{collection.model_name.cache_key}/query-#{query_signature}"
|
7
|
+
|
8
|
+
if collection.loaded?
|
9
|
+
size = collection.size
|
10
|
+
if size > 0
|
11
|
+
timestamp = collection.max_by(×tamp_column).public_send(timestamp_column)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
column_type = type_for_attribute(timestamp_column.to_s)
|
15
|
+
column = "#{connection.quote_table_name(collection.table_name)}.#{connection.quote_column_name(timestamp_column)}"
|
16
|
+
|
17
|
+
query = collection
|
18
|
+
.unscope(:select)
|
19
|
+
.select("COUNT(*) AS #{connection.quote_column_name("size")}", "MAX(#{column}) AS timestamp")
|
20
|
+
.unscope(:order)
|
21
|
+
result = connection.select_one(query)
|
22
|
+
|
23
|
+
if result.blank?
|
24
|
+
size = 0
|
25
|
+
timestamp = nil
|
26
|
+
else
|
27
|
+
size = result["size"]
|
28
|
+
timestamp = column_type.deserialize(result["timestamp"])
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
if timestamp
|
34
|
+
"#{key}-#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
|
35
|
+
else
|
36
|
+
"#{key}-#{size}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|