activerecord 3.0.0 → 4.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 +7 -0
- data/CHANGELOG.md +2102 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +35 -44
- data/examples/performance.rb +110 -100
- data/lib/active_record/aggregations.rb +59 -75
- data/lib/active_record/associations/alias_tracker.rb +76 -0
- data/lib/active_record/associations/association.rb +248 -0
- data/lib/active_record/associations/association_scope.rb +135 -0
- data/lib/active_record/associations/belongs_to_association.rb +60 -59
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
- data/lib/active_record/associations/builder/association.rb +108 -0
- data/lib/active_record/associations/builder/belongs_to.rb +98 -0
- data/lib/active_record/associations/builder/collection_association.rb +89 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
- data/lib/active_record/associations/builder/has_many.rb +15 -0
- data/lib/active_record/associations/builder/has_one.rb +25 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +608 -0
- data/lib/active_record/associations/collection_proxy.rb +986 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
- data/lib/active_record/associations/has_many_association.rb +83 -76
- data/lib/active_record/associations/has_many_through_association.rb +147 -66
- data/lib/active_record/associations/has_one_association.rb +67 -108
- data/lib/active_record/associations/has_one_through_association.rb +21 -25
- data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_dependency.rb +235 -0
- data/lib/active_record/associations/join_helper.rb +45 -0
- data/lib/active_record/associations/preloader/association.rb +121 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +63 -0
- data/lib/active_record/associations/preloader.rb +178 -0
- data/lib/active_record/associations/singular_association.rb +64 -0
- data/lib/active_record/associations/through_association.rb +87 -0
- data/lib/active_record/associations.rb +512 -1224
- data/lib/active_record/attribute_assignment.rb +201 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
- data/lib/active_record/attribute_methods/dirty.rb +51 -28
- data/lib/active_record/attribute_methods/primary_key.rb +94 -22
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +63 -72
- data/lib/active_record/attribute_methods/serialization.rb +162 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
- data/lib/active_record/attribute_methods/write.rb +39 -13
- data/lib/active_record/attribute_methods.rb +362 -29
- data/lib/active_record/autosave_association.rb +132 -75
- data/lib/active_record/base.rb +83 -1627
- data/lib/active_record/callbacks.rb +69 -47
- data/lib/active_record/coders/yaml_column.rb +38 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
- data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
- data/lib/active_record/connection_adapters/column.rb +318 -0
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
- data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +463 -0
- data/lib/active_record/counter_cache.rb +108 -101
- data/lib/active_record/dynamic_matchers.rb +131 -0
- data/lib/active_record/errors.rb +54 -13
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +703 -785
- data/lib/active_record/inheritance.rb +200 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +69 -60
- data/lib/active_record/locking/pessimistic.rb +34 -12
- data/lib/active_record/log_subscriber.rb +40 -6
- data/lib/active_record/migration/command_recorder.rb +164 -0
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +614 -216
- data/lib/active_record/model_schema.rb +345 -0
- data/lib/active_record/nested_attributes.rb +248 -119
- data/lib/active_record/null_relation.rb +65 -0
- data/lib/active_record/persistence.rb +275 -57
- data/lib/active_record/query_cache.rb +29 -9
- data/lib/active_record/querying.rb +62 -0
- data/lib/active_record/railtie.rb +135 -21
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +17 -5
- data/lib/active_record/railties/databases.rake +249 -359
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +30 -0
- data/lib/active_record/reflection.rb +283 -103
- data/lib/active_record/relation/batches.rb +38 -34
- data/lib/active_record/relation/calculations.rb +252 -139
- data/lib/active_record/relation/delegation.rb +125 -0
- data/lib/active_record/relation/finder_methods.rb +182 -188
- data/lib/active_record/relation/merger.rb +161 -0
- data/lib/active_record/relation/predicate_builder.rb +86 -21
- data/lib/active_record/relation/query_methods.rb +917 -134
- data/lib/active_record/relation/spawn_methods.rb +53 -92
- data/lib/active_record/relation.rb +405 -143
- data/lib/active_record/result.rb +67 -0
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +168 -0
- data/lib/active_record/schema.rb +20 -14
- data/lib/active_record/schema_dumper.rb +55 -46
- data/lib/active_record/schema_migration.rb +39 -0
- data/lib/active_record/scoping/default.rb +146 -0
- data/lib/active_record/scoping/named.rb +175 -0
- data/lib/active_record/scoping.rb +82 -0
- data/lib/active_record/serialization.rb +8 -46
- data/lib/active_record/serializers/xml_serializer.rb +21 -68
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +156 -0
- data/lib/active_record/tasks/database_tasks.rb +203 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +57 -28
- data/lib/active_record/timestamp.rb +49 -18
- data/lib/active_record/transactions.rb +106 -63
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +25 -24
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +123 -83
- data/lib/active_record/validations.rb +29 -29
- data/lib/active_record/version.rb +7 -5
- data/lib/active_record.rb +83 -34
- data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
- data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
- data/lib/rails/generators/active_record.rb +4 -8
- metadata +163 -121
- data/CHANGELOG +0 -6023
- data/examples/associations.png +0 -0
- data/lib/active_record/association_preload.rb +0 -403
- data/lib/active_record/associations/association_collection.rb +0 -562
- data/lib/active_record/associations/association_proxy.rb +0 -295
- data/lib/active_record/associations/through_association_scope.rb +0 -154
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
- data/lib/active_record/dynamic_finder_match.rb +0 -53
- data/lib/active_record/dynamic_scope_match.rb +0 -32
- data/lib/active_record/named_scope.rb +0 -138
- data/lib/active_record/observer.rb +0 -140
- data/lib/active_record/session_store.rb +0 -340
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/array/wrap'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
# = Active Record Callbacks
|
5
3
|
#
|
@@ -25,15 +23,19 @@ module ActiveRecord
|
|
25
23
|
# Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
|
26
24
|
# <tt>after_rollback</tt>.
|
27
25
|
#
|
28
|
-
#
|
26
|
+
# Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
|
27
|
+
# is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
|
28
|
+
# are instantiated as well.
|
29
|
+
#
|
30
|
+
# That's a total of twelve callbacks, which gives you immense power to react and prepare for each state in the
|
29
31
|
# Active Record life cycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar,
|
30
|
-
# except that each <tt>
|
32
|
+
# except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
|
31
33
|
#
|
32
34
|
# Examples:
|
33
35
|
# class CreditCard < ActiveRecord::Base
|
34
36
|
# # Strip everything but digits, so the user can specify "555 234 34" or
|
35
|
-
# # "5552-3434"
|
36
|
-
# before_validation(:
|
37
|
+
# # "5552-3434" and both will mean "55523434"
|
38
|
+
# before_validation(on: :create) do
|
37
39
|
# self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
|
38
40
|
# end
|
39
41
|
# end
|
@@ -69,7 +71,7 @@ module ActiveRecord
|
|
69
71
|
#
|
70
72
|
# Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
|
71
73
|
# run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
|
72
|
-
# where the +before_destroy+
|
74
|
+
# where the +before_destroy+ method is overridden:
|
73
75
|
#
|
74
76
|
# class Topic < ActiveRecord::Base
|
75
77
|
# def before_destroy() destroy_author end
|
@@ -81,7 +83,7 @@ module ActiveRecord
|
|
81
83
|
#
|
82
84
|
# In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
|
83
85
|
# So, use the callback macros when you want to ensure that a certain callback is called for the entire
|
84
|
-
# hierarchy, and use the regular
|
86
|
+
# hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
|
85
87
|
# to decide whether they want to call +super+ and trigger the inherited callbacks.
|
86
88
|
#
|
87
89
|
# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
|
@@ -185,14 +187,6 @@ module ActiveRecord
|
|
185
187
|
# 'puts "Evaluated after parents are destroyed"'
|
186
188
|
# end
|
187
189
|
#
|
188
|
-
# == The +after_find+ and +after_initialize+ exceptions
|
189
|
-
#
|
190
|
-
# Because +after_find+ and +after_initialize+ are called for each object found and instantiated by a finder,
|
191
|
-
# such as <tt>Base.find(:all)</tt>, we've had to implement a simple performance constraint (50% more speed
|
192
|
-
# on a simple test case). Unlike all the other callbacks, +after_find+ and +after_initialize+ will only be
|
193
|
-
# run if an explicit implementation is defined (<tt>def after_find</tt>). In that case, all of the
|
194
|
-
# callback types will be called.
|
195
|
-
#
|
196
190
|
# == <tt>before_validation*</tt> returning statements
|
197
191
|
#
|
198
192
|
# If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be
|
@@ -206,6 +200,40 @@ module ActiveRecord
|
|
206
200
|
# Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
|
207
201
|
# methods on the model, which are called last.
|
208
202
|
#
|
203
|
+
# == Ordering callbacks
|
204
|
+
#
|
205
|
+
# Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
|
206
|
+
# callback (+log_children+ in this case) should be executed before the children get destroyed by the +dependent: destroy+ option.
|
207
|
+
#
|
208
|
+
# Let's look at the code below:
|
209
|
+
#
|
210
|
+
# class Topic < ActiveRecord::Base
|
211
|
+
# has_many :children, dependent: destroy
|
212
|
+
#
|
213
|
+
# before_destroy :log_children
|
214
|
+
#
|
215
|
+
# private
|
216
|
+
# def log_children
|
217
|
+
# # Child processing
|
218
|
+
# end
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
|
222
|
+
# because the +destroy+ callback gets executed first. You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
|
223
|
+
#
|
224
|
+
# class Topic < ActiveRecord::Base
|
225
|
+
# has_many :children, dependent: destroy
|
226
|
+
#
|
227
|
+
# before_destroy :log_children, prepend: true
|
228
|
+
#
|
229
|
+
# private
|
230
|
+
# def log_children
|
231
|
+
# # Child processing
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
#
|
235
|
+
# This way, the +before_destroy+ gets executed before the <tt>dependent: destroy</tt> is called, and the data is still available.
|
236
|
+
#
|
209
237
|
# == Transactions
|
210
238
|
#
|
211
239
|
# The entire callback chain of a +save+, <tt>save!</tt>, or +destroy+ call runs
|
@@ -220,13 +248,21 @@ module ActiveRecord
|
|
220
248
|
#
|
221
249
|
# == Debugging callbacks
|
222
250
|
#
|
223
|
-
#
|
224
|
-
#
|
251
|
+
# The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
|
252
|
+
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
|
253
|
+
# defines what part of the chain the callback runs in.
|
254
|
+
#
|
255
|
+
# To find all callbacks in the before_save callback chain:
|
256
|
+
#
|
257
|
+
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
|
258
|
+
#
|
259
|
+
# Returns an array of callback objects that form the before_save chain.
|
260
|
+
#
|
261
|
+
# To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
|
225
262
|
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
# options{}]
|
263
|
+
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
|
264
|
+
#
|
265
|
+
# Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
|
230
266
|
#
|
231
267
|
module Callbacks
|
232
268
|
extend ActiveSupport::Concern
|
@@ -238,51 +274,37 @@ module ActiveRecord
|
|
238
274
|
:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
|
239
275
|
]
|
240
276
|
|
277
|
+
module ClassMethods
|
278
|
+
include ActiveModel::Callbacks
|
279
|
+
end
|
280
|
+
|
241
281
|
included do
|
242
|
-
extend ActiveModel::Callbacks
|
243
282
|
include ActiveModel::Validations::Callbacks
|
244
283
|
|
245
284
|
define_model_callbacks :initialize, :find, :touch, :only => :after
|
246
285
|
define_model_callbacks :save, :create, :update, :destroy
|
247
286
|
end
|
248
287
|
|
249
|
-
module ClassMethods
|
250
|
-
def method_added(meth)
|
251
|
-
super
|
252
|
-
if CALLBACKS.include?(meth.to_sym)
|
253
|
-
ActiveSupport::Deprecation.warn("Base##{meth} has been deprecated, please use Base.#{meth} :method instead", caller[0,1])
|
254
|
-
send(meth.to_sym, meth.to_sym)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
288
|
def destroy #:nodoc:
|
260
|
-
|
289
|
+
run_callbacks(:destroy) { super }
|
261
290
|
end
|
262
291
|
|
263
292
|
def touch(*) #:nodoc:
|
264
|
-
|
265
|
-
end
|
266
|
-
|
267
|
-
def deprecated_callback_method(symbol) #:nodoc:
|
268
|
-
if respond_to?(symbol, true)
|
269
|
-
ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base##{symbol} :method_name instead")
|
270
|
-
send(symbol)
|
271
|
-
end
|
293
|
+
run_callbacks(:touch) { super }
|
272
294
|
end
|
273
295
|
|
274
296
|
private
|
275
297
|
|
276
298
|
def create_or_update #:nodoc:
|
277
|
-
|
299
|
+
run_callbacks(:save) { super }
|
278
300
|
end
|
279
301
|
|
280
|
-
def
|
281
|
-
|
302
|
+
def create_record #:nodoc:
|
303
|
+
run_callbacks(:create) { super }
|
282
304
|
end
|
283
305
|
|
284
|
-
def
|
285
|
-
|
306
|
+
def update_record(*) #:nodoc:
|
307
|
+
run_callbacks(:update) { super }
|
286
308
|
end
|
287
309
|
end
|
288
310
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Coders # :nodoc:
|
5
|
+
class YAMLColumn # :nodoc:
|
6
|
+
|
7
|
+
attr_accessor :object_class
|
8
|
+
|
9
|
+
def initialize(object_class = Object)
|
10
|
+
@object_class = object_class
|
11
|
+
end
|
12
|
+
|
13
|
+
def dump(obj)
|
14
|
+
return if obj.nil?
|
15
|
+
|
16
|
+
unless obj.is_a?(object_class)
|
17
|
+
raise SerializationTypeMismatch,
|
18
|
+
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
|
19
|
+
end
|
20
|
+
YAML.dump obj
|
21
|
+
end
|
22
|
+
|
23
|
+
def load(yaml)
|
24
|
+
return object_class.new if object_class != Object && yaml.nil?
|
25
|
+
return yaml unless yaml.is_a?(String) && yaml =~ /^---/
|
26
|
+
obj = YAML.load(yaml)
|
27
|
+
|
28
|
+
unless obj.is_a?(object_class) || obj.nil?
|
29
|
+
raise SerializationTypeMismatch,
|
30
|
+
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
|
31
|
+
end
|
32
|
+
obj ||= object_class.new if object_class != Object
|
33
|
+
|
34
|
+
obj
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|