activerecord 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -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 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- 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 +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- 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 +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- 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 +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -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 +1 -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 -2
- 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 +23 -16
- 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 +18 -11
- 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 +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- 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/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- 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 +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- 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 +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -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/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -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 +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- 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 +16 -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 +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- 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 +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- 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 +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- 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,5 +1,3 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module NullRelation # :nodoc:
|
5
3
|
def exec_queries
|
@@ -14,7 +12,7 @@ module ActiveRecord
|
|
14
12
|
0
|
15
13
|
end
|
16
14
|
|
17
|
-
def update_all(_updates
|
15
|
+
def update_all(_updates)
|
18
16
|
0
|
19
17
|
end
|
20
18
|
|
@@ -30,10 +28,18 @@ module ActiveRecord
|
|
30
28
|
true
|
31
29
|
end
|
32
30
|
|
31
|
+
def none?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
33
35
|
def any?
|
34
36
|
false
|
35
37
|
end
|
36
38
|
|
39
|
+
def one?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
37
43
|
def many?
|
38
44
|
false
|
39
45
|
end
|
@@ -62,9 +68,7 @@ module ActiveRecord
|
|
62
68
|
calculate :maximum, nil
|
63
69
|
end
|
64
70
|
|
65
|
-
def calculate(operation, _column_name
|
66
|
-
# TODO: Remove _options argument as soon we remove support to
|
67
|
-
# activerecord-deprecated_finders.
|
71
|
+
def calculate(operation, _column_name)
|
68
72
|
if [:count, :sum, :size].include? operation
|
69
73
|
group_values.any? ? Hash.new : 0
|
70
74
|
elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
|
@@ -74,8 +78,12 @@ module ActiveRecord
|
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
77
|
-
def exists?(
|
81
|
+
def exists?(_conditions = :none)
|
78
82
|
false
|
79
83
|
end
|
84
|
+
|
85
|
+
def or(other)
|
86
|
+
other.spawn
|
87
|
+
end
|
80
88
|
end
|
81
89
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
# = Active Record Persistence
|
2
|
+
# = Active Record \Persistence
|
3
3
|
module Persistence
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
@@ -96,7 +96,8 @@ module ActiveRecord
|
|
96
96
|
# Returns true if the record is persisted, i.e. it's not a new record and it was
|
97
97
|
# not destroyed, otherwise returns false.
|
98
98
|
def persisted?
|
99
|
-
|
99
|
+
sync_with_transaction_state
|
100
|
+
!(@new_record || @destroyed)
|
100
101
|
end
|
101
102
|
|
102
103
|
# Saves the model.
|
@@ -105,41 +106,49 @@ module ActiveRecord
|
|
105
106
|
# the existing record gets updated.
|
106
107
|
#
|
107
108
|
# By default, save always run validations. If any of them fail the action
|
108
|
-
# is cancelled and
|
109
|
+
# is cancelled and #save returns +false+. However, if you supply
|
109
110
|
# validate: false, validations are bypassed altogether. See
|
110
111
|
# ActiveRecord::Validations for more information.
|
111
112
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
113
|
+
# By default, #save also sets the +updated_at+/+updated_on+ attributes to
|
114
|
+
# the current time. However, if you supply <tt>touch: false</tt>, these
|
115
|
+
# timestamps will not be updated.
|
116
|
+
#
|
117
|
+
# There's a series of callbacks associated with #save. If any of the
|
118
|
+
# <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled and
|
119
|
+
# #save returns +false+. See ActiveRecord::Callbacks for further
|
115
120
|
# details.
|
116
121
|
#
|
117
122
|
# Attributes marked as readonly are silently ignored if the record is
|
118
123
|
# being updated.
|
119
|
-
def save(*)
|
120
|
-
create_or_update
|
124
|
+
def save(*args)
|
125
|
+
create_or_update(*args)
|
121
126
|
rescue ActiveRecord::RecordInvalid
|
122
127
|
false
|
123
128
|
end
|
124
129
|
|
125
130
|
# Saves the model.
|
126
131
|
#
|
127
|
-
# If the model is new a record gets created in the database, otherwise
|
132
|
+
# If the model is new, a record gets created in the database, otherwise
|
128
133
|
# the existing record gets updated.
|
129
134
|
#
|
130
|
-
# With
|
135
|
+
# With #save! validations always run. If any of them fail
|
131
136
|
# ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
|
132
137
|
# for more information.
|
133
138
|
#
|
134
|
-
#
|
135
|
-
# the
|
136
|
-
#
|
139
|
+
# By default, #save! also sets the +updated_at+/+updated_on+ attributes to
|
140
|
+
# the current time. However, if you supply <tt>touch: false</tt>, these
|
141
|
+
# timestamps will not be updated.
|
142
|
+
#
|
143
|
+
# There's a series of callbacks associated with #save!. If any of
|
144
|
+
# the <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled
|
145
|
+
# and #save! raises ActiveRecord::RecordNotSaved. See
|
137
146
|
# ActiveRecord::Callbacks for further details.
|
138
147
|
#
|
139
148
|
# Attributes marked as readonly are silently ignored if the record is
|
140
149
|
# being updated.
|
141
|
-
def save!(*)
|
142
|
-
create_or_update || raise(RecordNotSaved.new("Failed to save the record", self))
|
150
|
+
def save!(*args)
|
151
|
+
create_or_update(*args) || raise(RecordNotSaved.new("Failed to save the record", self))
|
143
152
|
end
|
144
153
|
|
145
154
|
# Deletes the record in the database and freezes this instance to
|
@@ -149,6 +158,8 @@ module ActiveRecord
|
|
149
158
|
# The row is simply removed with an SQL +DELETE+ statement on the
|
150
159
|
# record's primary key, and no callbacks are executed.
|
151
160
|
#
|
161
|
+
# Note that this will also delete records marked as {#readonly?}[rdoc-ref:Core#readonly?].
|
162
|
+
#
|
152
163
|
# To enforce the object's +before_destroy+ and +after_destroy+
|
153
164
|
# callbacks or any <tt>:dependent</tt> association
|
154
165
|
# options, use <tt>#destroy</tt>.
|
@@ -161,10 +172,10 @@ module ActiveRecord
|
|
161
172
|
# Deletes the record in the database and freezes this instance to reflect
|
162
173
|
# that no changes should be made (since they can't be persisted).
|
163
174
|
#
|
164
|
-
# There's a series of callbacks associated with
|
165
|
-
#
|
166
|
-
# and
|
167
|
-
# ActiveRecord::Callbacks for further details.
|
175
|
+
# There's a series of callbacks associated with #destroy. If the
|
176
|
+
# <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
|
177
|
+
# and #destroy returns +false+.
|
178
|
+
# See ActiveRecord::Callbacks for further details.
|
168
179
|
def destroy
|
169
180
|
raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
|
170
181
|
destroy_associations
|
@@ -177,12 +188,12 @@ module ActiveRecord
|
|
177
188
|
# Deletes the record in the database and freezes this instance to reflect
|
178
189
|
# that no changes should be made (since they can't be persisted).
|
179
190
|
#
|
180
|
-
# There's a series of callbacks associated with
|
181
|
-
#
|
182
|
-
# and
|
183
|
-
# ActiveRecord::Callbacks for further details.
|
191
|
+
# There's a series of callbacks associated with #destroy!. If the
|
192
|
+
# <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
|
193
|
+
# and #destroy! raises ActiveRecord::RecordNotDestroyed.
|
194
|
+
# See ActiveRecord::Callbacks for further details.
|
184
195
|
def destroy!
|
185
|
-
destroy ||
|
196
|
+
destroy || _raise_record_not_destroyed
|
186
197
|
end
|
187
198
|
|
188
199
|
# Returns an instance of the specified +klass+ with the attributes of the
|
@@ -194,19 +205,21 @@ module ActiveRecord
|
|
194
205
|
# instance using the companies/company partial instead of clients/client.
|
195
206
|
#
|
196
207
|
# Note: The new instance will share a link to the same attributes as the original class.
|
197
|
-
#
|
208
|
+
# Therefore the sti column value will still be the same.
|
209
|
+
# Any change to the attributes on either instance will affect both instances.
|
210
|
+
# If you want to change the sti column as well, use #becomes! instead.
|
198
211
|
def becomes(klass)
|
199
212
|
became = klass.new
|
200
213
|
became.instance_variable_set("@attributes", @attributes)
|
201
|
-
|
202
|
-
became.instance_variable_set("@changed_attributes",
|
214
|
+
became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
|
215
|
+
became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
|
203
216
|
became.instance_variable_set("@new_record", new_record?)
|
204
217
|
became.instance_variable_set("@destroyed", destroyed?)
|
205
|
-
became.
|
218
|
+
became.errors.copy!(errors)
|
206
219
|
became
|
207
220
|
end
|
208
221
|
|
209
|
-
# Wrapper around
|
222
|
+
# Wrapper around #becomes that also changes the instance's sti column value.
|
210
223
|
# This is especially useful if you want to persist the changed class in your
|
211
224
|
# database.
|
212
225
|
#
|
@@ -226,19 +239,19 @@ module ActiveRecord
|
|
226
239
|
# This is especially useful for boolean flags on existing records. Also note that
|
227
240
|
#
|
228
241
|
# * Validation is skipped.
|
229
|
-
# * Callbacks are invoked.
|
242
|
+
# * \Callbacks are invoked.
|
230
243
|
# * updated_at/updated_on column is updated if that column is available.
|
231
244
|
# * Updates all the attributes that are dirty in this object.
|
232
245
|
#
|
233
|
-
# This method raises an
|
246
|
+
# This method raises an ActiveRecord::ActiveRecordError if the
|
234
247
|
# attribute is marked as readonly.
|
235
248
|
#
|
236
|
-
# See also
|
249
|
+
# See also #update_column.
|
237
250
|
def update_attribute(name, value)
|
238
251
|
name = name.to_s
|
239
252
|
verify_readonly_attribute(name)
|
240
|
-
|
241
|
-
save(validate: false)
|
253
|
+
public_send("#{name}=", value)
|
254
|
+
save(validate: false) if changed?
|
242
255
|
end
|
243
256
|
|
244
257
|
# Updates the attributes of the model from the passed-in hash and saves the
|
@@ -255,7 +268,7 @@ module ActiveRecord
|
|
255
268
|
|
256
269
|
alias update_attributes update
|
257
270
|
|
258
|
-
# Updates its receiver just like
|
271
|
+
# Updates its receiver just like #update but calls #save! instead
|
259
272
|
# of +save+, so an exception is raised if the record is invalid.
|
260
273
|
def update!(attributes)
|
261
274
|
# The following transaction covers any possible database side-effects of the
|
@@ -282,11 +295,12 @@ module ActiveRecord
|
|
282
295
|
# the database, but take into account that in consequence the regular update
|
283
296
|
# procedures are totally bypassed. In particular:
|
284
297
|
#
|
285
|
-
# * Validations are skipped.
|
286
|
-
# * Callbacks are skipped.
|
298
|
+
# * \Validations are skipped.
|
299
|
+
# * \Callbacks are skipped.
|
287
300
|
# * +updated_at+/+updated_on+ are not updated.
|
301
|
+
# * However, attributes are serialized with the same rules as ActiveRecord::Relation#update_all
|
288
302
|
#
|
289
|
-
# This method raises an
|
303
|
+
# This method raises an ActiveRecord::ActiveRecordError when called on new
|
290
304
|
# objects, or when at least one of the attributes is marked as readonly.
|
291
305
|
def update_columns(attributes)
|
292
306
|
raise ActiveRecordError, "cannot update a new record" if new_record?
|
@@ -314,41 +328,51 @@ module ActiveRecord
|
|
314
328
|
self
|
315
329
|
end
|
316
330
|
|
317
|
-
# Wrapper around
|
331
|
+
# Wrapper around #increment that saves the record. This method differs from
|
318
332
|
# its non-bang version in that it passes through the attribute setter.
|
319
333
|
# Saving is not subjected to validation checks. Returns +true+ if the
|
320
334
|
# record could be saved.
|
321
335
|
def increment!(attribute, by = 1)
|
322
|
-
increment(attribute, by)
|
336
|
+
increment(attribute, by)
|
337
|
+
change = public_send(attribute) - (attribute_was(attribute.to_s) || 0)
|
338
|
+
self.class.update_counters(id, attribute => change)
|
339
|
+
clear_attribute_change(attribute) # eww
|
340
|
+
self
|
323
341
|
end
|
324
342
|
|
325
343
|
# Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
|
326
344
|
# The decrement is performed directly on the underlying attribute, no setter is invoked.
|
327
345
|
# Only makes sense for number-based attributes. Returns +self+.
|
328
346
|
def decrement(attribute, by = 1)
|
329
|
-
|
330
|
-
self[attribute] -= by
|
331
|
-
self
|
347
|
+
increment(attribute, -by)
|
332
348
|
end
|
333
349
|
|
334
|
-
# Wrapper around
|
350
|
+
# Wrapper around #decrement that saves the record. This method differs from
|
335
351
|
# its non-bang version in that it passes through the attribute setter.
|
336
352
|
# Saving is not subjected to validation checks. Returns +true+ if the
|
337
353
|
# record could be saved.
|
338
354
|
def decrement!(attribute, by = 1)
|
339
|
-
|
355
|
+
increment!(attribute, -by)
|
340
356
|
end
|
341
357
|
|
342
358
|
# Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
|
343
359
|
# if the predicate returns +true+ the attribute will become +false+. This
|
344
360
|
# method toggles directly the underlying value without calling any setter.
|
345
361
|
# Returns +self+.
|
362
|
+
#
|
363
|
+
# Example:
|
364
|
+
#
|
365
|
+
# user = User.first
|
366
|
+
# user.banned? # => false
|
367
|
+
# user.toggle(:banned)
|
368
|
+
# user.banned? # => true
|
369
|
+
#
|
346
370
|
def toggle(attribute)
|
347
|
-
self[attribute] = !
|
371
|
+
self[attribute] = !public_send("#{attribute}?")
|
348
372
|
self
|
349
373
|
end
|
350
374
|
|
351
|
-
# Wrapper around
|
375
|
+
# Wrapper around #toggle that saves the record. This method differs from
|
352
376
|
# its non-bang version in that it passes through the attribute setter.
|
353
377
|
# Saving is not subjected to validation checks. Returns +true+ if the
|
354
378
|
# record could be saved.
|
@@ -371,7 +395,7 @@ module ActiveRecord
|
|
371
395
|
# Attributes are reloaded from the database, and caches busted, in
|
372
396
|
# particular the associations cache and the QueryCache.
|
373
397
|
#
|
374
|
-
# If the record no longer exists in the database
|
398
|
+
# If the record no longer exists in the database ActiveRecord::RecordNotFound
|
375
399
|
# is raised. Otherwise, in addition to the in-place modification the method
|
376
400
|
# returns +self+ for convenience.
|
377
401
|
#
|
@@ -405,8 +429,6 @@ module ActiveRecord
|
|
405
429
|
# end
|
406
430
|
#
|
407
431
|
def reload(options = nil)
|
408
|
-
clear_aggregation_cache
|
409
|
-
clear_association_cache
|
410
432
|
self.class.connection.clear_query_cache
|
411
433
|
|
412
434
|
fresh_object =
|
@@ -421,19 +443,22 @@ module ActiveRecord
|
|
421
443
|
self
|
422
444
|
end
|
423
445
|
|
424
|
-
# Saves the record with the updated_at/on attributes set to the current time
|
446
|
+
# Saves the record with the updated_at/on attributes set to the current time
|
447
|
+
# or the time specified.
|
425
448
|
# Please note that no validation is performed and only the +after_touch+,
|
426
449
|
# +after_commit+ and +after_rollback+ callbacks are executed.
|
427
450
|
#
|
451
|
+
# This method can be passed attribute names and an optional time argument.
|
428
452
|
# If attribute names are passed, they are updated along with updated_at/on
|
429
|
-
# attributes.
|
453
|
+
# attributes. If no time argument is passed, the current time is used as default.
|
430
454
|
#
|
431
|
-
# product.touch # updates updated_at/on
|
455
|
+
# product.touch # updates updated_at/on with current time
|
456
|
+
# product.touch(time: Time.new(2015, 2, 16, 0, 0, 0)) # updates updated_at/on with specified time
|
432
457
|
# product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
|
433
458
|
# product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
|
434
459
|
#
|
435
|
-
# If used along with
|
436
|
-
# associated object.
|
460
|
+
# If used along with {belongs_to}[rdoc-ref:Associations::ClassMethods#belongs_to]
|
461
|
+
# then +touch+ will invoke +touch+ method on associated object.
|
437
462
|
#
|
438
463
|
# class Brake < ActiveRecord::Base
|
439
464
|
# belongs_to :car, touch: true
|
@@ -452,26 +477,38 @@ module ActiveRecord
|
|
452
477
|
# ball = Ball.new
|
453
478
|
# ball.touch(:updated_at) # => raises ActiveRecordError
|
454
479
|
#
|
455
|
-
def touch(*names)
|
480
|
+
def touch(*names, time: nil)
|
456
481
|
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
457
482
|
|
483
|
+
time ||= current_time_from_proper_timezone
|
458
484
|
attributes = timestamp_attributes_for_update_in_model
|
459
485
|
attributes.concat(names)
|
460
486
|
|
461
487
|
unless attributes.empty?
|
462
|
-
current_time = current_time_from_proper_timezone
|
463
488
|
changes = {}
|
464
489
|
|
465
490
|
attributes.each do |column|
|
466
491
|
column = column.to_s
|
467
|
-
changes[column] = write_attribute(column,
|
492
|
+
changes[column] = write_attribute(column, time)
|
468
493
|
end
|
469
494
|
|
470
|
-
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
471
|
-
|
472
495
|
clear_attribute_changes(changes.keys)
|
473
496
|
primary_key = self.class.primary_key
|
474
|
-
self.class.unscoped.where(primary_key =>
|
497
|
+
scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
|
498
|
+
|
499
|
+
if locking_enabled?
|
500
|
+
locking_column = self.class.locking_column
|
501
|
+
scope = scope.where(locking_column => _read_attribute(locking_column))
|
502
|
+
changes[locking_column] = increment_lock
|
503
|
+
end
|
504
|
+
|
505
|
+
result = scope.update_all(changes) == 1
|
506
|
+
|
507
|
+
if !result && locking_enabled?
|
508
|
+
raise ActiveRecord::StaleObjectError.new(self, "touch")
|
509
|
+
end
|
510
|
+
|
511
|
+
result
|
475
512
|
else
|
476
513
|
true
|
477
514
|
end
|
@@ -488,20 +525,12 @@ module ActiveRecord
|
|
488
525
|
end
|
489
526
|
|
490
527
|
def relation_for_destroy
|
491
|
-
|
492
|
-
column = self.class.columns_hash[pk]
|
493
|
-
substitute = self.class.connection.substitute_at(column)
|
494
|
-
|
495
|
-
relation = self.class.unscoped.where(
|
496
|
-
self.class.arel_table[pk].eq(substitute))
|
497
|
-
|
498
|
-
relation.bind_values = [[column, id]]
|
499
|
-
relation
|
528
|
+
self.class.unscoped.where(self.class.primary_key => id)
|
500
529
|
end
|
501
530
|
|
502
|
-
def create_or_update
|
531
|
+
def create_or_update(*args)
|
503
532
|
raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
|
504
|
-
result = new_record? ? _create_record : _update_record
|
533
|
+
result = new_record? ? _create_record : _update_record(*args)
|
505
534
|
result != false
|
506
535
|
end
|
507
536
|
|
@@ -531,5 +560,16 @@ module ActiveRecord
|
|
531
560
|
def verify_readonly_attribute(name)
|
532
561
|
raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
|
533
562
|
end
|
563
|
+
|
564
|
+
def _raise_record_not_destroyed
|
565
|
+
@_association_destroy_exception ||= nil
|
566
|
+
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy the record", self)
|
567
|
+
ensure
|
568
|
+
@_association_destroy_exception = nil
|
569
|
+
end
|
570
|
+
|
571
|
+
def belongs_to_touch_method
|
572
|
+
:touch
|
573
|
+
end
|
534
574
|
end
|
535
575
|
end
|
@@ -6,8 +6,8 @@ module ActiveRecord
|
|
6
6
|
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
7
7
|
delegate :find_by, :find_by!, to: :all
|
8
8
|
delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
|
9
|
-
delegate :find_each, :find_in_batches, to: :all
|
10
|
-
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
|
9
|
+
delegate :find_each, :find_in_batches, :in_batches, to: :all
|
10
|
+
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
|
11
11
|
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
|
12
12
|
:having, :create_with, :uniq, :distinct, :references, :none, :unscope, to: :all
|
13
13
|
delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
|
@@ -55,11 +55,12 @@ module ActiveRecord
|
|
55
55
|
# The use of this method should be restricted to complicated SQL queries that can't be executed
|
56
56
|
# using the ActiveRecord::Calculations class methods. Look into those before using this.
|
57
57
|
#
|
58
|
-
#
|
58
|
+
# Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
|
59
|
+
# # => 12
|
59
60
|
#
|
60
|
-
#
|
61
|
+
# ==== Parameters
|
61
62
|
#
|
62
|
-
#
|
63
|
+
# * +sql+ - An SQL statement which should return a count query from the database, see the example above.
|
63
64
|
def count_by_sql(sql)
|
64
65
|
sql = sanitize_conditions(sql)
|
65
66
|
connection.select_value(sql, "#{name} Count").to_i
|