activerecord 3.0.0.beta → 3.0.0.beta2
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.
- data/CHANGELOG +8 -1
- data/lib/active_record.rb +9 -6
- data/lib/active_record/aggregations.rb +5 -0
- data/lib/active_record/association_preload.rb +7 -2
- data/lib/active_record/associations.rb +74 -54
- data/lib/active_record/associations/association_collection.rb +1 -0
- data/lib/active_record/associations/association_proxy.rb +2 -1
- data/lib/active_record/associations/has_many_association.rb +4 -0
- data/lib/active_record/associations/has_many_through_association.rb +1 -0
- data/lib/active_record/attribute_methods/dirty.rb +11 -9
- data/lib/active_record/attribute_methods/primary_key.rb +6 -0
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/base.rb +57 -212
- data/lib/active_record/callbacks.rb +10 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +24 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +10 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +22 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +34 -8
- data/lib/active_record/dynamic_finder_match.rb +3 -0
- data/lib/active_record/errors.rb +165 -0
- data/lib/active_record/fixtures.rb +1 -0
- data/lib/active_record/migration.rb +8 -6
- data/lib/active_record/named_scope.rb +14 -5
- data/lib/active_record/nested_attributes.rb +6 -2
- data/lib/active_record/query_cache.rb +2 -0
- data/lib/active_record/railtie.rb +30 -19
- data/lib/active_record/railties/databases.rake +13 -7
- data/lib/active_record/railties/{subscriber.rb → log_subscriber.rb} +7 -2
- data/lib/active_record/reflection.rb +5 -3
- data/lib/active_record/relation.rb +13 -2
- data/lib/active_record/relation/batches.rb +84 -0
- data/lib/active_record/relation/calculations.rb +2 -0
- data/lib/active_record/relation/finder_methods.rb +13 -2
- data/lib/active_record/relation/predicate_builder.rb +2 -7
- data/lib/active_record/relation/query_methods.rb +20 -27
- data/lib/active_record/relation/spawn_methods.rb +18 -28
- data/lib/active_record/schema.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +2 -4
- data/lib/active_record/version.rb +3 -2
- data/lib/{generators → rails/generators}/active_record.rb +0 -0
- data/lib/{generators → rails/generators}/active_record/migration/migration_generator.rb +1 -1
- data/lib/{generators → rails/generators}/active_record/migration/templates/migration.rb +0 -0
- data/lib/{generators → rails/generators}/active_record/model/model_generator.rb +1 -1
- data/lib/{generators → rails/generators}/active_record/model/templates/migration.rb +0 -0
- data/lib/{generators → rails/generators}/active_record/model/templates/model.rb +0 -0
- data/lib/{generators → rails/generators}/active_record/observer/observer_generator.rb +1 -1
- data/lib/{generators → rails/generators}/active_record/observer/templates/observer.rb +0 -0
- data/lib/{generators → rails/generators}/active_record/session_migration/session_migration_generator.rb +1 -1
- data/lib/{generators → rails/generators}/active_record/session_migration/templates/migration.rb +0 -0
- metadata +61 -34
- data/lib/active_record/batches.rb +0 -79
data/CHANGELOG
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
*
|
1
|
+
*Rails 3.0.0 [Beta 2] (pending)*
|
2
|
+
|
3
|
+
* To prefix the table names of all models in a module, define self.table_name_prefix on the module. #4032 [Andrew White]
|
4
|
+
|
5
|
+
* Silenced "SHOW FIELDS" and "SET SQL_AUTO_IS_NULL=0" statements from the MySQL driver to improve log signal to noise ration in development [DHH]
|
6
|
+
|
7
|
+
|
8
|
+
*Rails 3.0.0 [Beta 1] (February 4th, 2010)*
|
2
9
|
|
3
10
|
* PostgreSQLAdapter: set time_zone to UTC when Base.default_timezone == :utc so that Postgres doesn't incorrectly offset-adjust values inserted into TIMESTAMP WITH TIME ZONE columns. #3777 [Jack Christensen]
|
4
11
|
|
data/lib/active_record.rb
CHANGED
@@ -30,7 +30,6 @@ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include
|
|
30
30
|
|
31
31
|
require 'active_support'
|
32
32
|
require 'active_model'
|
33
|
-
require 'arel'
|
34
33
|
|
35
34
|
module ActiveRecord
|
36
35
|
extend ActiveSupport::Autoload
|
@@ -38,8 +37,8 @@ module ActiveRecord
|
|
38
37
|
eager_autoload do
|
39
38
|
autoload :VERSION
|
40
39
|
|
41
|
-
autoload :ActiveRecordError, 'active_record/
|
42
|
-
autoload :ConnectionNotEstablished, 'active_record/
|
40
|
+
autoload :ActiveRecordError, 'active_record/errors'
|
41
|
+
autoload :ConnectionNotEstablished, 'active_record/errors'
|
43
42
|
|
44
43
|
autoload :Aggregations
|
45
44
|
autoload :AssociationPreload
|
@@ -55,10 +54,10 @@ module ActiveRecord
|
|
55
54
|
autoload :Calculations
|
56
55
|
autoload :PredicateBuilder
|
57
56
|
autoload :SpawnMethods
|
57
|
+
autoload :Batches
|
58
58
|
end
|
59
59
|
|
60
60
|
autoload :Base
|
61
|
-
autoload :Batches
|
62
61
|
autoload :Callbacks
|
63
62
|
autoload :DynamicFinderMatch
|
64
63
|
autoload :DynamicScopeMatch
|
@@ -106,6 +105,7 @@ module ActiveRecord
|
|
106
105
|
|
107
106
|
eager_autoload do
|
108
107
|
autoload :AbstractAdapter
|
108
|
+
autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -113,5 +113,8 @@ module ActiveRecord
|
|
113
113
|
autoload :TestFixtures, 'active_record/fixtures'
|
114
114
|
end
|
115
115
|
|
116
|
-
|
117
|
-
|
116
|
+
ActiveSupport.on_load(:active_record) do
|
117
|
+
Arel::Table.engine = Arel::Sql::Engine.new(self)
|
118
|
+
end
|
119
|
+
|
120
|
+
I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
|
@@ -213,6 +213,11 @@ module ActiveRecord
|
|
213
213
|
module_eval do
|
214
214
|
define_method(name) do |*args|
|
215
215
|
force_reload = args.first || false
|
216
|
+
|
217
|
+
unless instance_variable_defined?("@#{name}")
|
218
|
+
instance_variable_set("@#{name}", nil)
|
219
|
+
end
|
220
|
+
|
216
221
|
if (instance_variable_get("@#{name}").nil? || force_reload) && (!allow_nil || mapping.any? {|pair| !read_attribute(pair.first).nil? })
|
217
222
|
attrs = mapping.collect {|pair| read_attribute(pair.first)}
|
218
223
|
object = case constructor
|
@@ -126,7 +126,7 @@ module ActiveRecord
|
|
126
126
|
parent_records.each do |parent_record|
|
127
127
|
association_proxy = parent_record.send(reflection_name)
|
128
128
|
association_proxy.loaded
|
129
|
-
association_proxy.target.push
|
129
|
+
association_proxy.target.push(*Array.wrap(associated_record))
|
130
130
|
|
131
131
|
association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
|
132
132
|
end
|
@@ -159,6 +159,11 @@ module ActiveRecord
|
|
159
159
|
association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record)
|
160
160
|
end
|
161
161
|
end
|
162
|
+
|
163
|
+
id_to_record_map.each do |id, records|
|
164
|
+
next if seen_keys.include?(id.to_s)
|
165
|
+
records.each {|record| record.send("set_#{reflection_name}_target", nil) }
|
166
|
+
end
|
162
167
|
end
|
163
168
|
|
164
169
|
# Given a collection of ActiveRecord objects, constructs a Hash which maps
|
@@ -324,7 +329,7 @@ module ActiveRecord
|
|
324
329
|
klass = klass_name.constantize
|
325
330
|
|
326
331
|
table_name = klass.quoted_table_name
|
327
|
-
primary_key = klass.primary_key
|
332
|
+
primary_key = reflection.options[:primary_key] || klass.primary_key
|
328
333
|
column_type = klass.columns.detect{|c| c.name == primary_key}.type
|
329
334
|
|
330
335
|
ids = id_map.keys.map do |id|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/module/delegation'
|
2
2
|
require 'active_support/core_ext/enumerable'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
|
@@ -85,6 +86,15 @@ module ActiveRecord
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
89
|
+
# This error is raised when trying to destroy a parent instance in a N:1, 1:1 assosications
|
90
|
+
# (has_many, has_one) when there is at least 1 child assosociated instance.
|
91
|
+
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
92
|
+
class DeleteRestrictionError < ActiveRecordError #:nodoc:
|
93
|
+
def initialize(reflection)
|
94
|
+
super("Cannot delete record because of dependent #{reflection.name}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
88
98
|
# See ActiveRecord::Associations::ClassMethods for documentation.
|
89
99
|
module Associations # :nodoc:
|
90
100
|
extend ActiveSupport::Concern
|
@@ -111,8 +121,11 @@ module ActiveRecord
|
|
111
121
|
private
|
112
122
|
# Gets the specified association instance if it responds to :loaded?, nil otherwise.
|
113
123
|
def association_instance_get(name)
|
114
|
-
|
115
|
-
|
124
|
+
ivar = "@#{name}"
|
125
|
+
if instance_variable_defined?(ivar)
|
126
|
+
association = instance_variable_get(ivar)
|
127
|
+
association if association.respond_to?(:loaded?)
|
128
|
+
end
|
116
129
|
end
|
117
130
|
|
118
131
|
# Set the specified association instance.
|
@@ -827,6 +840,8 @@ module ActiveRecord
|
|
827
840
|
# objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
|
828
841
|
# objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. *Warning:* This option is ignored when also using
|
829
842
|
# the <tt>:through</tt> option.
|
843
|
+
# the <tt>:through</tt> option. If set to <tt>:restrict</tt>
|
844
|
+
# this object cannot be deleted if it has any associated object.
|
830
845
|
# [:finder_sql]
|
831
846
|
# Specify a complete SQL statement to fetch the association. This is a good way to go for complex
|
832
847
|
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added.
|
@@ -1207,7 +1222,7 @@ module ActiveRecord
|
|
1207
1222
|
# * <tt>Developer#projects.empty?</tt>
|
1208
1223
|
# * <tt>Developer#projects.size</tt>
|
1209
1224
|
# * <tt>Developer#projects.find(id)</tt>
|
1210
|
-
# * <tt>Developer#
|
1225
|
+
# * <tt>Developer#projects.exists?(...)</tt>
|
1211
1226
|
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>)
|
1212
1227
|
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>)
|
1213
1228
|
# The declaration may include an options hash to specialize the behavior of the association.
|
@@ -1465,9 +1480,15 @@ module ActiveRecord
|
|
1465
1480
|
|
1466
1481
|
# Creates before_destroy callback methods that nullify, delete or destroy
|
1467
1482
|
# has_many associated objects, according to the defined :dependent rule.
|
1483
|
+
# If the association is marked as :dependent => :restrict, create a callback
|
1484
|
+
# that prevents deleting entirely.
|
1468
1485
|
#
|
1469
1486
|
# See HasManyAssociation#delete_records. Dependent associations
|
1470
1487
|
# delete children, otherwise foreign key is set to NULL.
|
1488
|
+
# See HasManyAssociation#delete_records. Dependent associations
|
1489
|
+
# delete children if the option is set to :destroy or :delete_all, set the
|
1490
|
+
# foreign key to NULL if the option is set to :nullify, and do not touch the
|
1491
|
+
# child records if the option is set to :restrict.
|
1471
1492
|
#
|
1472
1493
|
# The +extra_conditions+ parameter, which is not used within the main
|
1473
1494
|
# Active Record codebase, is meant to allow plugins to define extra
|
@@ -1527,68 +1548,76 @@ module ActiveRecord
|
|
1527
1548
|
%@#{dependent_conditions}@)
|
1528
1549
|
end
|
1529
1550
|
CALLBACK
|
1551
|
+
when :restrict
|
1552
|
+
method_name = "has_many_dependent_restrict_for_#{reflection.name}".to_sym
|
1553
|
+
define_method(method_name) do
|
1554
|
+
unless send(reflection.name).empty?
|
1555
|
+
raise DeleteRestrictionError.new(reflection)
|
1556
|
+
end
|
1557
|
+
end
|
1558
|
+
before_destroy method_name
|
1530
1559
|
else
|
1531
|
-
raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :
|
1560
|
+
raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, :nullify or :restrict (#{reflection.options[:dependent].inspect})"
|
1532
1561
|
end
|
1533
1562
|
end
|
1534
1563
|
end
|
1535
1564
|
|
1536
1565
|
# Creates before_destroy callback methods that nullify, delete or destroy
|
1537
1566
|
# has_one associated objects, according to the defined :dependent rule.
|
1567
|
+
# If the association is marked as :dependent => :restrict, create a callback
|
1568
|
+
# that prevents deleting entirely.
|
1538
1569
|
def configure_dependency_for_has_one(reflection)
|
1539
1570
|
if reflection.options.include?(:dependent)
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
# Retrieve the associated object and delete it. The retrieval
|
1552
|
-
# is necessary because there may be multiple associated objects
|
1553
|
-
# with foreign keys pointing to this object, and we only want
|
1554
|
-
# to delete the correct one, not all of them.
|
1555
|
-
association = send(reflection.name)
|
1556
|
-
association.delete unless association.nil?
|
1557
|
-
end
|
1558
|
-
before_destroy method_name
|
1571
|
+
name = reflection.options[:dependent]
|
1572
|
+
method_name = :"has_one_dependent_#{name}_for_#{reflection.name}"
|
1573
|
+
|
1574
|
+
case name
|
1575
|
+
when :destroy, :delete
|
1576
|
+
class_eval <<-eoruby, __FILE__, __LINE__ + 1
|
1577
|
+
def #{method_name}
|
1578
|
+
association = #{reflection.name}
|
1579
|
+
association.#{name} if association
|
1580
|
+
end
|
1581
|
+
eoruby
|
1559
1582
|
when :nullify
|
1560
|
-
|
1583
|
+
class_eval <<-eoruby, __FILE__, __LINE__ + 1
|
1584
|
+
def #{method_name}
|
1585
|
+
association = #{reflection.name}
|
1586
|
+
association.update_attribute(#{reflection.primary_key_name.inspect}, nil) if association
|
1587
|
+
end
|
1588
|
+
eoruby
|
1589
|
+
when :restrict
|
1590
|
+
method_name = "has_one_dependent_restrict_for_#{reflection.name}".to_sym
|
1561
1591
|
define_method(method_name) do
|
1562
|
-
|
1563
|
-
|
1592
|
+
unless send(reflection.name).nil?
|
1593
|
+
raise DeleteRestrictionError.new(reflection)
|
1594
|
+
end
|
1564
1595
|
end
|
1565
1596
|
before_destroy method_name
|
1566
1597
|
else
|
1567
|
-
raise ArgumentError, "The :dependent option expects either :destroy, :delete or :
|
1598
|
+
raise ArgumentError, "The :dependent option expects either :destroy, :delete, :nullify or :restrict (#{reflection.options[:dependent].inspect})"
|
1568
1599
|
end
|
1600
|
+
|
1601
|
+
before_destroy method_name
|
1569
1602
|
end
|
1570
1603
|
end
|
1571
1604
|
|
1572
1605
|
def configure_dependency_for_belongs_to(reflection)
|
1573
1606
|
if reflection.options.include?(:dependent)
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
association = send(reflection.name)
|
1579
|
-
association.destroy unless association.nil?
|
1580
|
-
end
|
1581
|
-
after_destroy method_name
|
1582
|
-
when :delete
|
1583
|
-
method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym
|
1584
|
-
define_method(method_name) do
|
1585
|
-
association = send(reflection.name)
|
1586
|
-
association.delete unless association.nil?
|
1587
|
-
end
|
1588
|
-
after_destroy method_name
|
1589
|
-
else
|
1590
|
-
raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
|
1607
|
+
name = reflection.options[:dependent]
|
1608
|
+
|
1609
|
+
unless [:destroy, :delete].include?(name)
|
1610
|
+
raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
|
1591
1611
|
end
|
1612
|
+
|
1613
|
+
method_name = :"belongs_to_dependent_#{name}_for_#{reflection.name}"
|
1614
|
+
class_eval <<-eoruby, __FILE__, __LINE__ + 1
|
1615
|
+
def #{method_name}
|
1616
|
+
association = #{reflection.name}
|
1617
|
+
association.#{name} if association
|
1618
|
+
end
|
1619
|
+
eoruby
|
1620
|
+
after_destroy method_name
|
1592
1621
|
end
|
1593
1622
|
end
|
1594
1623
|
|
@@ -1686,15 +1715,6 @@ module ActiveRecord
|
|
1686
1715
|
reflection
|
1687
1716
|
end
|
1688
1717
|
|
1689
|
-
def using_limitable_reflections?(reflections)
|
1690
|
-
reflections.collect(&:collection?).length.zero?
|
1691
|
-
end
|
1692
|
-
|
1693
|
-
def column_aliases(join_dependency)
|
1694
|
-
join_dependency.joins.collect{|join| join.column_names_with_alias.collect{|column_name, aliased_name|
|
1695
|
-
"#{connection.quote_table_name join.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}"}}.flatten.join(", ")
|
1696
|
-
end
|
1697
|
-
|
1698
1718
|
def add_association_callbacks(association_name, options)
|
1699
1719
|
callbacks = %w(before_add after_add before_remove after_remove)
|
1700
1720
|
callbacks.each do |callback_name|
|
@@ -2011,7 +2031,7 @@ module ActiveRecord
|
|
2011
2031
|
[aliased_table[foreign_key].eq(parent_table[reflection.options[:primary_key] || parent.primary_key])]
|
2012
2032
|
end
|
2013
2033
|
when :belongs_to
|
2014
|
-
[aliased_table[reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name])]
|
2034
|
+
[aliased_table[options[:primary_key] || reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name])]
|
2015
2035
|
end
|
2016
2036
|
|
2017
2037
|
unless klass.descends_from_active_record?
|
@@ -49,10 +49,11 @@ module ActiveRecord
|
|
49
49
|
alias_method :proxy_respond_to?, :respond_to?
|
50
50
|
alias_method :proxy_extend, :extend
|
51
51
|
delegate :to_param, :to => :proxy_target
|
52
|
-
instance_methods.each { |m| undef_method m unless m =~
|
52
|
+
instance_methods.each { |m| undef_method m unless m =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ }
|
53
53
|
|
54
54
|
def initialize(owner, reflection)
|
55
55
|
@owner, @reflection = owner, reflection
|
56
|
+
@updated = false
|
56
57
|
reflection.check_validity!
|
57
58
|
Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
|
58
59
|
reset
|
@@ -5,6 +5,10 @@ module ActiveRecord
|
|
5
5
|
# If the association has a <tt>:through</tt> option further specialization
|
6
6
|
# is provided by its child HasManyThroughAssociation.
|
7
7
|
class HasManyAssociation < AssociationCollection #:nodoc:
|
8
|
+
def initialize(owner, reflection)
|
9
|
+
@finder_sql = nil
|
10
|
+
super
|
11
|
+
end
|
8
12
|
protected
|
9
13
|
def owner_quoted_id
|
10
14
|
if @reflection.options[:primary_key]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
module Dirty
|
@@ -18,7 +20,7 @@ module ActiveRecord
|
|
18
20
|
def save_with_dirty(*args) #:nodoc:
|
19
21
|
if status = save_without_dirty(*args)
|
20
22
|
@previously_changed = changes
|
21
|
-
changed_attributes.clear
|
23
|
+
@changed_attributes.clear
|
22
24
|
end
|
23
25
|
status
|
24
26
|
end
|
@@ -26,16 +28,16 @@ module ActiveRecord
|
|
26
28
|
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
27
29
|
def save_with_dirty!(*args) #:nodoc:
|
28
30
|
save_without_dirty!(*args).tap do
|
29
|
-
@previously_changed = changes
|
30
|
-
changed_attributes.clear
|
31
|
+
@previously_changed = changes
|
32
|
+
@changed_attributes.clear
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
36
|
# <tt>reload</tt> the record and clears changed attributes.
|
35
37
|
def reload_with_dirty(*args) #:nodoc:
|
36
38
|
reload_without_dirty(*args).tap do
|
37
|
-
|
38
|
-
changed_attributes.clear
|
39
|
+
@previously_changed.clear
|
40
|
+
@changed_attributes.clear
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -45,12 +47,12 @@ module ActiveRecord
|
|
45
47
|
attr = attr.to_s
|
46
48
|
|
47
49
|
# The attribute already has an unsaved change.
|
48
|
-
if
|
49
|
-
old = changed_attributes[attr]
|
50
|
-
changed_attributes.delete(attr) unless field_changed?(attr, old, value)
|
50
|
+
if attribute_changed?(attr)
|
51
|
+
old = @changed_attributes[attr]
|
52
|
+
@changed_attributes.delete(attr) unless field_changed?(attr, old, value)
|
51
53
|
else
|
52
54
|
old = clone_attribute_value(:read_attribute, attr)
|
53
|
-
changed_attributes[attr] = old if field_changed?(attr, old, value)
|
55
|
+
@changed_attributes[attr] = old if field_changed?(attr, old, value)
|
54
56
|
end
|
55
57
|
|
56
58
|
# Carry on.
|
@@ -3,6 +3,12 @@ module ActiveRecord
|
|
3
3
|
module PrimaryKey
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
# Returns this record's primary key value wrapped in an Array
|
7
|
+
# or nil if the record is a new_record?
|
8
|
+
def to_key
|
9
|
+
new_record? ? nil : [ send(self.class.primary_key) ]
|
10
|
+
end
|
11
|
+
|
6
12
|
module ClassMethods
|
7
13
|
# Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the
|
8
14
|
# primary_key_prefix_type setting, though.
|
data/lib/active_record/base.rb
CHANGED
@@ -11,174 +11,14 @@ require 'active_support/core_ext/hash/deep_merge'
|
|
11
11
|
require 'active_support/core_ext/hash/indifferent_access'
|
12
12
|
require 'active_support/core_ext/hash/slice'
|
13
13
|
require 'active_support/core_ext/string/behavior'
|
14
|
-
require 'active_support/core_ext/object/
|
14
|
+
require 'active_support/core_ext/object/singleton_class'
|
15
15
|
require 'active_support/core_ext/module/delegation'
|
16
|
+
require 'active_support/core_ext/object/duplicable'
|
17
|
+
require 'active_support/core_ext/object/blank'
|
18
|
+
require 'arel'
|
19
|
+
require 'active_record/errors'
|
16
20
|
|
17
21
|
module ActiveRecord #:nodoc:
|
18
|
-
# Generic Active Record exception class.
|
19
|
-
class ActiveRecordError < StandardError
|
20
|
-
end
|
21
|
-
|
22
|
-
# Raised when the single-table inheritance mechanism fails to locate the subclass
|
23
|
-
# (for example due to improper usage of column that +inheritance_column+ points to).
|
24
|
-
class SubclassNotFound < ActiveRecordError #:nodoc:
|
25
|
-
end
|
26
|
-
|
27
|
-
# Raised when an object assigned to an association has an incorrect type.
|
28
|
-
#
|
29
|
-
# class Ticket < ActiveRecord::Base
|
30
|
-
# has_many :patches
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# class Patch < ActiveRecord::Base
|
34
|
-
# belongs_to :ticket
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# # Comments are not patches, this assignment raises AssociationTypeMismatch.
|
38
|
-
# @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
|
39
|
-
class AssociationTypeMismatch < ActiveRecordError
|
40
|
-
end
|
41
|
-
|
42
|
-
# Raised when unserialized object's type mismatches one specified for serializable field.
|
43
|
-
class SerializationTypeMismatch < ActiveRecordError
|
44
|
-
end
|
45
|
-
|
46
|
-
# Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
|
47
|
-
class AdapterNotSpecified < ActiveRecordError
|
48
|
-
end
|
49
|
-
|
50
|
-
# Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
|
51
|
-
class AdapterNotFound < ActiveRecordError
|
52
|
-
end
|
53
|
-
|
54
|
-
# Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
|
55
|
-
class ConnectionNotEstablished < ActiveRecordError
|
56
|
-
end
|
57
|
-
|
58
|
-
# Raised when Active Record cannot find record by given id or set of ids.
|
59
|
-
class RecordNotFound < ActiveRecordError
|
60
|
-
end
|
61
|
-
|
62
|
-
# Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
|
63
|
-
# saved because record is invalid.
|
64
|
-
class RecordNotSaved < ActiveRecordError
|
65
|
-
end
|
66
|
-
|
67
|
-
# Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
|
68
|
-
class StatementInvalid < ActiveRecordError
|
69
|
-
end
|
70
|
-
|
71
|
-
# Raised when SQL statement is invalid and the application gets a blank result.
|
72
|
-
class ThrowResult < ActiveRecordError
|
73
|
-
end
|
74
|
-
|
75
|
-
# Parent class for all specific exceptions which wrap database driver exceptions
|
76
|
-
# provides access to the original exception also.
|
77
|
-
class WrappedDatabaseException < StatementInvalid
|
78
|
-
attr_reader :original_exception
|
79
|
-
|
80
|
-
def initialize(message, original_exception)
|
81
|
-
super(message)
|
82
|
-
@original_exception = original_exception
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Raised when a record cannot be inserted because it would violate a uniqueness constraint.
|
87
|
-
class RecordNotUnique < WrappedDatabaseException
|
88
|
-
end
|
89
|
-
|
90
|
-
# Raised when a record cannot be inserted or updated because it references a non-existent record.
|
91
|
-
class InvalidForeignKey < WrappedDatabaseException
|
92
|
-
end
|
93
|
-
|
94
|
-
# Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
|
95
|
-
# does not match number of expected variables.
|
96
|
-
#
|
97
|
-
# For example, in
|
98
|
-
#
|
99
|
-
# Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
|
100
|
-
#
|
101
|
-
# two placeholders are given but only one variable to fill them.
|
102
|
-
class PreparedStatementInvalid < ActiveRecordError
|
103
|
-
end
|
104
|
-
|
105
|
-
# Raised on attempt to save stale record. Record is stale when it's being saved in another query after
|
106
|
-
# instantiation, for example, when two users edit the same wiki page and one starts editing and saves
|
107
|
-
# the page before the other.
|
108
|
-
#
|
109
|
-
# Read more about optimistic locking in ActiveRecord::Locking module RDoc.
|
110
|
-
class StaleObjectError < ActiveRecordError
|
111
|
-
end
|
112
|
-
|
113
|
-
# Raised when association is being configured improperly or
|
114
|
-
# user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
|
115
|
-
class ConfigurationError < ActiveRecordError
|
116
|
-
end
|
117
|
-
|
118
|
-
# Raised on attempt to update record that is instantiated as read only.
|
119
|
-
class ReadOnlyRecord < ActiveRecordError
|
120
|
-
end
|
121
|
-
|
122
|
-
# ActiveRecord::Transactions::ClassMethods.transaction uses this exception
|
123
|
-
# to distinguish a deliberate rollback from other exceptional situations.
|
124
|
-
# Normally, raising an exception will cause the +transaction+ method to rollback
|
125
|
-
# the database transaction *and* pass on the exception. But if you raise an
|
126
|
-
# ActiveRecord::Rollback exception, then the database transaction will be rolled back,
|
127
|
-
# without passing on the exception.
|
128
|
-
#
|
129
|
-
# For example, you could do this in your controller to rollback a transaction:
|
130
|
-
#
|
131
|
-
# class BooksController < ActionController::Base
|
132
|
-
# def create
|
133
|
-
# Book.transaction do
|
134
|
-
# book = Book.new(params[:book])
|
135
|
-
# book.save!
|
136
|
-
# if today_is_friday?
|
137
|
-
# # The system must fail on Friday so that our support department
|
138
|
-
# # won't be out of job. We silently rollback this transaction
|
139
|
-
# # without telling the user.
|
140
|
-
# raise ActiveRecord::Rollback, "Call tech support!"
|
141
|
-
# end
|
142
|
-
# end
|
143
|
-
# # ActiveRecord::Rollback is the only exception that won't be passed on
|
144
|
-
# # by ActiveRecord::Base.transaction, so this line will still be reached
|
145
|
-
# # even on Friday.
|
146
|
-
# redirect_to root_url
|
147
|
-
# end
|
148
|
-
# end
|
149
|
-
class Rollback < ActiveRecordError
|
150
|
-
end
|
151
|
-
|
152
|
-
# Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
|
153
|
-
class DangerousAttributeError < ActiveRecordError
|
154
|
-
end
|
155
|
-
|
156
|
-
# Raised when unknown attributes are supplied via mass assignment.
|
157
|
-
class UnknownAttributeError < NoMethodError
|
158
|
-
end
|
159
|
-
|
160
|
-
# Raised when an error occurred while doing a mass assignment to an attribute through the
|
161
|
-
# <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
|
162
|
-
# offending attribute.
|
163
|
-
class AttributeAssignmentError < ActiveRecordError
|
164
|
-
attr_reader :exception, :attribute
|
165
|
-
def initialize(message, exception, attribute)
|
166
|
-
@exception = exception
|
167
|
-
@attribute = attribute
|
168
|
-
@message = message
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Raised when there are multiple errors while doing a mass assignment through the +attributes+
|
173
|
-
# method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
|
174
|
-
# objects, each corresponding to the error while assigning to an attribute.
|
175
|
-
class MultiparameterAssignmentErrors < ActiveRecordError
|
176
|
-
attr_reader :errors
|
177
|
-
def initialize(errors)
|
178
|
-
@errors = errors
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
22
|
# Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
|
183
23
|
# which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
|
184
24
|
# is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain
|
@@ -498,6 +338,9 @@ module ActiveRecord #:nodoc:
|
|
498
338
|
# Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
|
499
339
|
# table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
|
500
340
|
# for tables in a shared database. By default, the prefix is the empty string.
|
341
|
+
#
|
342
|
+
# If you are organising your models within modules you can add a prefix to the models within a namespace by defining
|
343
|
+
# a singleton method in the parent module called table_name_prefix which returns your chosen prefix.
|
501
344
|
cattr_accessor :table_name_prefix, :instance_writer => false
|
502
345
|
@@table_name_prefix = ""
|
503
346
|
|
@@ -551,12 +394,13 @@ module ActiveRecord #:nodoc:
|
|
551
394
|
class << self # Class methods
|
552
395
|
def colorize_logging(*args)
|
553
396
|
ActiveSupport::Deprecation.warn "ActiveRecord::Base.colorize_logging and " <<
|
554
|
-
"config.active_record.colorize_logging are deprecated. Please use " <<
|
555
|
-
"Rails::
|
397
|
+
"config.active_record.colorize_logging are deprecated. Please use " <<
|
398
|
+
"Rails::LogSubscriber.colorize_logging or config.colorize_logging instead", caller
|
556
399
|
end
|
557
400
|
alias :colorize_logging= :colorize_logging
|
558
401
|
|
559
402
|
delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
|
403
|
+
delegate :find_each, :find_in_batches, :to => :scoped
|
560
404
|
delegate :select, :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped
|
561
405
|
delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped
|
562
406
|
|
@@ -924,7 +768,7 @@ module ActiveRecord #:nodoc:
|
|
924
768
|
contained = contained.singularize if parent.pluralize_table_names
|
925
769
|
contained << '_'
|
926
770
|
end
|
927
|
-
name = "#{
|
771
|
+
name = "#{full_table_name_prefix}#{contained}#{undecorated_table_name(base.name)}#{table_name_suffix}"
|
928
772
|
end
|
929
773
|
|
930
774
|
@quoted_table_name = nil
|
@@ -932,6 +776,10 @@ module ActiveRecord #:nodoc:
|
|
932
776
|
name
|
933
777
|
end
|
934
778
|
|
779
|
+
def full_table_name_prefix #:nodoc:
|
780
|
+
(parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
|
781
|
+
end
|
782
|
+
|
935
783
|
# Defines the column name for use with single table inheritance
|
936
784
|
# -- can be set in subclasses like so: self.inheritance_column = "type_id"
|
937
785
|
def inheritance_column
|
@@ -1202,6 +1050,12 @@ module ActiveRecord #:nodoc:
|
|
1202
1050
|
|
1203
1051
|
object.instance_variable_set(:'@attributes', record)
|
1204
1052
|
object.instance_variable_set(:'@attributes_cache', {})
|
1053
|
+
object.instance_variable_set(:@new_record, false)
|
1054
|
+
object.instance_variable_set(:@readonly, false)
|
1055
|
+
object.instance_variable_set(:@destroyed, false)
|
1056
|
+
object.instance_variable_set(:@marked_for_destruction, false)
|
1057
|
+
object.instance_variable_set(:@previously_changed, {})
|
1058
|
+
object.instance_variable_set(:@changed_attributes, {})
|
1205
1059
|
|
1206
1060
|
object.send(:_run_find_callbacks)
|
1207
1061
|
object.send(:_run_initialize_callbacks)
|
@@ -1443,7 +1297,7 @@ module ActiveRecord #:nodoc:
|
|
1443
1297
|
# <tt>options</tt> argument is the same as in find.
|
1444
1298
|
#
|
1445
1299
|
# class Person < ActiveRecord::Base
|
1446
|
-
# default_scope
|
1300
|
+
# default_scope order('last_name, first_name')
|
1447
1301
|
# end
|
1448
1302
|
def default_scope(options = {})
|
1449
1303
|
self.default_scoping << construct_finder_arel(options)
|
@@ -1667,13 +1521,19 @@ module ActiveRecord #:nodoc:
|
|
1667
1521
|
@attributes = attributes_from_column_definition
|
1668
1522
|
@attributes_cache = {}
|
1669
1523
|
@new_record = true
|
1524
|
+
@readonly = false
|
1525
|
+
@destroyed = false
|
1526
|
+
@marked_for_destruction = false
|
1527
|
+
@previously_changed = {}
|
1528
|
+
@changed_attributes = {}
|
1529
|
+
|
1670
1530
|
ensure_proper_type
|
1671
|
-
self.attributes = attributes unless attributes.nil?
|
1672
1531
|
|
1673
1532
|
if scope = self.class.send(:current_scoped_methods)
|
1674
1533
|
create_with = scope.scope_for_create
|
1675
1534
|
create_with.each { |att,value| self.send("#{att}=", value) } if create_with
|
1676
1535
|
end
|
1536
|
+
self.attributes = attributes unless attributes.nil?
|
1677
1537
|
|
1678
1538
|
result = yield self if block_given?
|
1679
1539
|
_run_initialize_callbacks
|
@@ -1731,7 +1591,7 @@ module ActiveRecord #:nodoc:
|
|
1731
1591
|
# user_path(user) # => "/users/Phusion"
|
1732
1592
|
def to_param
|
1733
1593
|
# We can't use alias_method here, because method 'id' optimizes itself on the fly.
|
1734
|
-
|
1594
|
+
id && id.to_s # Be sure to stringify the id for routes
|
1735
1595
|
end
|
1736
1596
|
|
1737
1597
|
# Returns a cache key that can be used to identify this record.
|
@@ -1758,12 +1618,17 @@ module ActiveRecord #:nodoc:
|
|
1758
1618
|
|
1759
1619
|
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet; otherwise, returns false.
|
1760
1620
|
def new_record?
|
1761
|
-
@new_record
|
1621
|
+
@new_record
|
1762
1622
|
end
|
1763
1623
|
|
1764
1624
|
# Returns true if this object has been destroyed, otherwise returns false.
|
1765
1625
|
def destroyed?
|
1766
|
-
@destroyed
|
1626
|
+
@destroyed
|
1627
|
+
end
|
1628
|
+
|
1629
|
+
# Returns if the record is persisted, i.e. it's not a new record and it was not destroyed.
|
1630
|
+
def persisted?
|
1631
|
+
!(new_record? || destroyed?)
|
1767
1632
|
end
|
1768
1633
|
|
1769
1634
|
# :call-seq:
|
@@ -1815,7 +1680,7 @@ module ActiveRecord #:nodoc:
|
|
1815
1680
|
# callbacks, Observer methods, or any <tt>:dependent</tt> association
|
1816
1681
|
# options, use <tt>#destroy</tt>.
|
1817
1682
|
def delete
|
1818
|
-
self.class.delete(id)
|
1683
|
+
self.class.delete(id) if persisted?
|
1819
1684
|
@destroyed = true
|
1820
1685
|
freeze
|
1821
1686
|
end
|
@@ -1823,7 +1688,7 @@ module ActiveRecord #:nodoc:
|
|
1823
1688
|
# Deletes the record in the database and freezes this instance to reflect that no changes should
|
1824
1689
|
# be made (since they can't be persisted).
|
1825
1690
|
def destroy
|
1826
|
-
|
1691
|
+
if persisted?
|
1827
1692
|
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
|
1828
1693
|
end
|
1829
1694
|
|
@@ -1843,6 +1708,7 @@ module ActiveRecord #:nodoc:
|
|
1843
1708
|
became.instance_variable_set("@attributes", @attributes)
|
1844
1709
|
became.instance_variable_set("@attributes_cache", @attributes_cache)
|
1845
1710
|
became.instance_variable_set("@new_record", new_record?)
|
1711
|
+
became.instance_variable_set("@destroyed", destroyed?)
|
1846
1712
|
became
|
1847
1713
|
end
|
1848
1714
|
|
@@ -1850,7 +1716,7 @@ module ActiveRecord #:nodoc:
|
|
1850
1716
|
# This is especially useful for boolean flags on existing records. The regular +update_attribute+ method
|
1851
1717
|
# in Base is replaced with this when the validations module is mixed in, which it is by default.
|
1852
1718
|
def update_attribute(name, value)
|
1853
|
-
send(name
|
1719
|
+
send("#{name}=", value)
|
1854
1720
|
save(:validate => false)
|
1855
1721
|
end
|
1856
1722
|
|
@@ -1925,7 +1791,7 @@ module ActiveRecord #:nodoc:
|
|
1925
1791
|
def reload(options = nil)
|
1926
1792
|
clear_aggregation_cache
|
1927
1793
|
clear_association_cache
|
1928
|
-
@attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
|
1794
|
+
@attributes.update(self.class.send(:with_exclusive_scope) { self.class.find(self.id, options) }.instance_variable_get('@attributes'))
|
1929
1795
|
@attributes_cache = {}
|
1930
1796
|
self
|
1931
1797
|
end
|
@@ -1994,10 +1860,9 @@ module ActiveRecord #:nodoc:
|
|
1994
1860
|
|
1995
1861
|
# Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
|
1996
1862
|
def attributes
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
end
|
1863
|
+
attrs = {}
|
1864
|
+
attribute_names.each { |name| attrs[name] = read_attribute(name) }
|
1865
|
+
attrs
|
2001
1866
|
end
|
2002
1867
|
|
2003
1868
|
# Returns an <tt>#inspect</tt>-like string for the value of the
|
@@ -2041,8 +1906,7 @@ module ActiveRecord #:nodoc:
|
|
2041
1906
|
def ==(comparison_object)
|
2042
1907
|
comparison_object.equal?(self) ||
|
2043
1908
|
(comparison_object.instance_of?(self.class) &&
|
2044
|
-
comparison_object.id == id &&
|
2045
|
-
!comparison_object.new_record?)
|
1909
|
+
comparison_object.id == id && !comparison_object.new_record?)
|
2046
1910
|
end
|
2047
1911
|
|
2048
1912
|
# Delegates to ==
|
@@ -2069,14 +1933,14 @@ module ActiveRecord #:nodoc:
|
|
2069
1933
|
# Returns duplicated record with unfreezed attributes.
|
2070
1934
|
def dup
|
2071
1935
|
obj = super
|
2072
|
-
obj.instance_variable_set('@attributes',
|
1936
|
+
obj.instance_variable_set('@attributes', @attributes.dup)
|
2073
1937
|
obj
|
2074
1938
|
end
|
2075
1939
|
|
2076
1940
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
2077
1941
|
# attributes will be marked as read only since they cannot be saved.
|
2078
1942
|
def readonly?
|
2079
|
-
|
1943
|
+
@readonly
|
2080
1944
|
end
|
2081
1945
|
|
2082
1946
|
# Marks this record as read only.
|
@@ -2096,10 +1960,10 @@ module ActiveRecord #:nodoc:
|
|
2096
1960
|
|
2097
1961
|
protected
|
2098
1962
|
def clone_attributes(reader_method = :read_attribute, attributes = {})
|
2099
|
-
|
2100
|
-
|
2101
|
-
attrs
|
1963
|
+
attribute_names.each do |name|
|
1964
|
+
attributes[name] = clone_attribute_value(reader_method, name)
|
2102
1965
|
end
|
1966
|
+
attributes
|
2103
1967
|
end
|
2104
1968
|
|
2105
1969
|
def clone_attribute_value(reader_method, attribute_name)
|
@@ -2198,26 +2062,6 @@ module ActiveRecord #:nodoc:
|
|
2198
2062
|
default
|
2199
2063
|
end
|
2200
2064
|
|
2201
|
-
# Returns a copy of the attributes hash where all the values have been safely quoted for use in
|
2202
|
-
# an SQL statement.
|
2203
|
-
def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
|
2204
|
-
quoted = {}
|
2205
|
-
connection = self.class.connection
|
2206
|
-
attribute_names.each do |name|
|
2207
|
-
if (column = column_for_attribute(name)) && (include_primary_key || !column.primary)
|
2208
|
-
value = read_attribute(name)
|
2209
|
-
|
2210
|
-
# We need explicit to_yaml because quote() does not properly convert Time/Date fields to YAML.
|
2211
|
-
if value && self.class.serialized_attributes.has_key?(name) && (value.acts_like?(:date) || value.acts_like?(:time))
|
2212
|
-
value = value.to_yaml
|
2213
|
-
end
|
2214
|
-
|
2215
|
-
quoted[name] = connection.quote(value, column)
|
2216
|
-
end
|
2217
|
-
end
|
2218
|
-
include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
|
2219
|
-
end
|
2220
|
-
|
2221
2065
|
# Returns a copy of the attributes hash where all the values have been safely quoted for use in
|
2222
2066
|
# an Arel insert/update method.
|
2223
2067
|
def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
|
@@ -2342,7 +2186,7 @@ module ActiveRecord #:nodoc:
|
|
2342
2186
|
|
2343
2187
|
# Returns a comma-separated pair list, like "key1 = val1, key2 = val2".
|
2344
2188
|
def comma_pair_list(hash)
|
2345
|
-
hash.
|
2189
|
+
hash.map { |k,v| "#{k} = #{v}" }.join(", ")
|
2346
2190
|
end
|
2347
2191
|
|
2348
2192
|
def quote_columns(quoter, hash)
|
@@ -2379,6 +2223,7 @@ module ActiveRecord #:nodoc:
|
|
2379
2223
|
extend QueryCache::ClassMethods
|
2380
2224
|
extend ActiveSupport::Benchmarkable
|
2381
2225
|
|
2226
|
+
include ActiveModel::Conversion
|
2382
2227
|
include Validations
|
2383
2228
|
include Locking::Optimistic, Locking::Pessimistic
|
2384
2229
|
include AttributeMethods
|
@@ -2388,16 +2233,16 @@ module ActiveRecord #:nodoc:
|
|
2388
2233
|
include AttributeMethods::Dirty
|
2389
2234
|
include Callbacks, ActiveModel::Observing, Timestamp
|
2390
2235
|
include Associations, AssociationPreload, NamedScope
|
2391
|
-
include ActiveModel::Conversion
|
2392
2236
|
|
2393
2237
|
# AutosaveAssociation needs to be included before Transactions, because we want
|
2394
2238
|
# #save_with_autosave_associations to be wrapped inside a transaction.
|
2395
2239
|
include AutosaveAssociation, NestedAttributes
|
2240
|
+
include Aggregations, Transactions, Reflection, Serialization
|
2396
2241
|
|
2397
|
-
|
2398
|
-
|
2242
|
+
NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner)
|
2399
2243
|
end
|
2400
2244
|
end
|
2401
2245
|
|
2402
2246
|
# TODO: Remove this and make it work with LAZY flag
|
2403
2247
|
require 'active_record/connection_adapters/abstract_adapter'
|
2248
|
+
ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
|