activerecord 4.1.0.beta2 → 4.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +622 -9
- data/MIT-LICENSE +1 -1
- data/lib/active_record.rb +1 -1
- data/lib/active_record/associations.rb +10 -7
- data/lib/active_record/associations/alias_tracker.rb +39 -29
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/association_scope.rb +56 -31
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -0
- data/lib/active_record/associations/builder/association.rb +6 -0
- data/lib/active_record/associations/builder/belongs_to.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +33 -9
- data/lib/active_record/associations/collection_proxy.rb +53 -5
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +8 -8
- data/lib/active_record/associations/preloader.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/attribute_methods.rb +28 -5
- data/lib/active_record/attribute_methods/dirty.rb +27 -4
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/attribute_methods/serialization.rb +18 -0
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/base.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +16 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -8
- data/lib/active_record/connection_adapters/abstract/transaction.rb +4 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/connection_specification.rb +200 -43
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +7 -1
- data/lib/active_record/connection_adapters/mysql_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/cast.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -17
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +25 -3
- data/lib/active_record/connection_handling.rb +64 -3
- data/lib/active_record/core.rb +28 -24
- data/lib/active_record/dynamic_matchers.rb +6 -2
- data/lib/active_record/enum.rb +111 -17
- data/lib/active_record/errors.rb +12 -0
- data/lib/active_record/fixtures.rb +13 -15
- data/lib/active_record/inheritance.rb +29 -9
- data/lib/active_record/integration.rb +4 -2
- data/lib/active_record/migration.rb +20 -7
- data/lib/active_record/migration/command_recorder.rb +18 -6
- data/lib/active_record/persistence.rb +10 -5
- data/lib/active_record/querying.rb +1 -0
- data/lib/active_record/railtie.rb +11 -8
- data/lib/active_record/railties/databases.rake +24 -38
- data/lib/active_record/relation.rb +3 -2
- data/lib/active_record/relation/batches.rb +24 -9
- data/lib/active_record/relation/finder_methods.rb +100 -11
- data/lib/active_record/relation/query_methods.rb +39 -27
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/sanitization.rb +7 -5
- data/lib/active_record/scoping.rb +5 -0
- data/lib/active_record/scoping/named.rb +6 -0
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +45 -23
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/transactions.rb +7 -7
- data/lib/active_record/validations/presence.rb +1 -1
- data/lib/active_record/version.rb +1 -1
- metadata +5 -6
- data/lib/active_record/associations/join_helper.rb +0 -36
@@ -91,8 +91,9 @@ module ActiveRecord
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def add_item_to_array(array, current_item, quoted)
|
94
|
-
if current_item.length == 0
|
95
|
-
|
94
|
+
return if !quoted && current_item.length == 0
|
95
|
+
|
96
|
+
if !quoted && current_item == 'NULL'
|
96
97
|
array.push nil
|
97
98
|
else
|
98
99
|
array.push current_item
|
@@ -35,11 +35,11 @@ module ActiveRecord
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def hstore_to_string(object)
|
38
|
+
def hstore_to_string(object, array_member = false)
|
39
39
|
if Hash === object
|
40
|
-
object.map { |k,v|
|
41
|
-
|
42
|
-
|
40
|
+
string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
|
41
|
+
string = escape_hstore(string) if array_member
|
42
|
+
string
|
43
43
|
else
|
44
44
|
object
|
45
45
|
end
|
@@ -49,10 +49,10 @@ module ActiveRecord
|
|
49
49
|
if string.nil?
|
50
50
|
nil
|
51
51
|
elsif String === string
|
52
|
-
Hash[string.scan(HstorePair).map { |k,v|
|
52
|
+
Hash[string.scan(HstorePair).map { |k, v|
|
53
53
|
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
54
54
|
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
55
|
-
[k,v]
|
55
|
+
[k, v]
|
56
56
|
}]
|
57
57
|
else
|
58
58
|
string
|
@@ -146,7 +146,7 @@ module ActiveRecord
|
|
146
146
|
|
147
147
|
def quote_and_escape(value)
|
148
148
|
case value
|
149
|
-
when "NULL"
|
149
|
+
when "NULL", Numeric
|
150
150
|
value
|
151
151
|
else
|
152
152
|
value = value.gsub(/\\/, ARRAY_ESCAPE)
|
@@ -46,8 +46,8 @@ module ActiveRecord
|
|
46
46
|
|
47
47
|
# Executes a SELECT query and returns an array of rows. Each row is an
|
48
48
|
# array of field values.
|
49
|
-
def select_rows(sql, name = nil)
|
50
|
-
|
49
|
+
def select_rows(sql, name = nil, binds = [])
|
50
|
+
exec_query(sql, name, binds).rows
|
51
51
|
end
|
52
52
|
|
53
53
|
# Executes an INSERT query and returns the new record's ID
|
@@ -121,7 +121,7 @@ module ActiveRecord
|
|
121
121
|
end
|
122
122
|
when Hash
|
123
123
|
case column.sql_type
|
124
|
-
when 'hstore' then PostgreSQLColumn.hstore_to_string(value)
|
124
|
+
when 'hstore' then PostgreSQLColumn.hstore_to_string(value, array_member)
|
125
125
|
when 'json' then PostgreSQLColumn.json_to_string(value)
|
126
126
|
else super(value, column)
|
127
127
|
end
|
@@ -126,6 +126,19 @@ module ActiveRecord
|
|
126
126
|
SQL
|
127
127
|
end
|
128
128
|
|
129
|
+
def index_name_exists?(table_name, index_name, default)
|
130
|
+
exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
|
131
|
+
SELECT COUNT(*)
|
132
|
+
FROM pg_class t
|
133
|
+
INNER JOIN pg_index d ON t.oid = d.indrelid
|
134
|
+
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
135
|
+
WHERE i.relkind = 'i'
|
136
|
+
AND i.relname = '#{index_name}'
|
137
|
+
AND t.relname = '#{table_name}'
|
138
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
|
139
|
+
SQL
|
140
|
+
end
|
141
|
+
|
129
142
|
# Returns an array of indexes for the given table.
|
130
143
|
def indexes(table_name, name = nil)
|
131
144
|
result = query(<<-SQL, 'SCHEMA')
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
# PostgreSQL-specific extensions to column definitions in a table.
|
47
47
|
class PostgreSQLColumn < Column #:nodoc:
|
48
48
|
attr_accessor :array
|
49
|
-
|
49
|
+
|
50
50
|
def initialize(name, default, oid_type, sql_type = nil, null = true)
|
51
51
|
@oid_type = oid_type
|
52
52
|
default_value = self.class.extract_value_from_default(default)
|
@@ -62,6 +62,14 @@ module ActiveRecord
|
|
62
62
|
@default_function = default if has_default_function?(default_value, default)
|
63
63
|
end
|
64
64
|
|
65
|
+
def number?
|
66
|
+
!array && super
|
67
|
+
end
|
68
|
+
|
69
|
+
def text?
|
70
|
+
!array && super
|
71
|
+
end
|
72
|
+
|
65
73
|
# :stopdoc:
|
66
74
|
class << self
|
67
75
|
include ConnectionAdapters::PostgreSQLColumn::Cast
|
@@ -578,11 +586,16 @@ module ActiveRecord
|
|
578
586
|
|
579
587
|
# Is this connection alive and ready for queries?
|
580
588
|
def active?
|
581
|
-
@connection.
|
589
|
+
@connection.query 'SELECT 1'
|
590
|
+
true
|
582
591
|
rescue PGError
|
583
592
|
false
|
584
593
|
end
|
585
594
|
|
595
|
+
def active_threadsafe?
|
596
|
+
@connection.connect_poll != PG::PGRES_POLLING_FAILED
|
597
|
+
end
|
598
|
+
|
586
599
|
# Close then reopen the connection.
|
587
600
|
def reconnect!
|
588
601
|
super
|
@@ -713,6 +726,10 @@ module ActiveRecord
|
|
713
726
|
!native_database_types[type].nil?
|
714
727
|
end
|
715
728
|
|
729
|
+
def update_table_definition(table_name, base) #:nodoc:
|
730
|
+
Table.new(table_name, base)
|
731
|
+
end
|
732
|
+
|
716
733
|
protected
|
717
734
|
|
718
735
|
# Returns the version of the connected PostgreSQL server.
|
@@ -792,7 +809,7 @@ module ActiveRecord
|
|
792
809
|
end
|
793
810
|
end
|
794
811
|
|
795
|
-
FEATURE_NOT_SUPPORTED = "0A000"
|
812
|
+
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
796
813
|
|
797
814
|
def exec_no_cache(sql, name, binds)
|
798
815
|
log(sql, name, binds) { @connection.async_exec(sql) }
|
@@ -841,7 +858,11 @@ module ActiveRecord
|
|
841
858
|
sql_key = sql_key(sql)
|
842
859
|
unless @statements.key? sql_key
|
843
860
|
nextkey = @statements.next_key
|
844
|
-
|
861
|
+
begin
|
862
|
+
@connection.prepare nextkey, sql
|
863
|
+
rescue => e
|
864
|
+
raise translate_exception_class(e, sql)
|
865
|
+
end
|
845
866
|
# Clear the queue
|
846
867
|
@connection.get_last_result
|
847
868
|
@statements[sql_key] = nextkey
|
@@ -865,6 +886,12 @@ module ActiveRecord
|
|
865
886
|
PostgreSQLColumn.money_precision = (postgresql_version >= 80300) ? 19 : 10
|
866
887
|
|
867
888
|
configure_connection
|
889
|
+
rescue ::PG::Error => error
|
890
|
+
if error.message.include?("does not exist")
|
891
|
+
raise ActiveRecord::NoDatabaseError.new(error.message)
|
892
|
+
else
|
893
|
+
raise error
|
894
|
+
end
|
868
895
|
end
|
869
896
|
|
870
897
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
@@ -920,14 +947,6 @@ module ActiveRecord
|
|
920
947
|
exec_query(sql, name, binds)
|
921
948
|
end
|
922
949
|
|
923
|
-
def select_raw(sql, name = nil)
|
924
|
-
res = execute(sql, name)
|
925
|
-
results = result_as_array(res)
|
926
|
-
fields = res.fields
|
927
|
-
res.clear
|
928
|
-
return fields, results
|
929
|
-
end
|
930
|
-
|
931
950
|
# Returns the list of a table's column names, data types, and default values.
|
932
951
|
#
|
933
952
|
# The underlying query is roughly:
|
@@ -969,17 +988,13 @@ module ActiveRecord
|
|
969
988
|
end
|
970
989
|
|
971
990
|
def extract_table_ref_from_insert_sql(sql)
|
972
|
-
sql[/into\s+([^\(]*).*values\s*\(/
|
991
|
+
sql[/into\s+([^\(]*).*values\s*\(/im]
|
973
992
|
$1.strip if $1
|
974
993
|
end
|
975
994
|
|
976
995
|
def create_table_definition(name, temporary, options, as = nil)
|
977
996
|
TableDefinition.new native_database_types, name, temporary, options, as
|
978
997
|
end
|
979
|
-
|
980
|
-
def update_table_definition(table_name, base)
|
981
|
-
Table.new(table_name, base)
|
982
|
-
end
|
983
998
|
end
|
984
999
|
end
|
985
1000
|
end
|
@@ -31,6 +31,12 @@ module ActiveRecord
|
|
31
31
|
db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
|
32
32
|
|
33
33
|
ConnectionAdapters::SQLite3Adapter.new(db, logger, config)
|
34
|
+
rescue Errno::ENOENT => error
|
35
|
+
if error.message.include?("No such file or directory")
|
36
|
+
raise ActiveRecord::NoDatabaseError.new(error.message)
|
37
|
+
else
|
38
|
+
raise error
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
@@ -149,6 +155,10 @@ module ActiveRecord
|
|
149
155
|
true
|
150
156
|
end
|
151
157
|
|
158
|
+
def supports_partial_index?
|
159
|
+
sqlite_version >= '3.8.0'
|
160
|
+
end
|
161
|
+
|
152
162
|
# Returns true, since this connection adapter supports prepared statement
|
153
163
|
# caching.
|
154
164
|
def supports_statement_cache?
|
@@ -337,8 +347,8 @@ module ActiveRecord
|
|
337
347
|
end
|
338
348
|
alias :create :insert_sql
|
339
349
|
|
340
|
-
def select_rows(sql, name = nil)
|
341
|
-
exec_query(sql, name).rows
|
350
|
+
def select_rows(sql, name = nil, binds = [])
|
351
|
+
exec_query(sql, name, binds).rows
|
342
352
|
end
|
343
353
|
|
344
354
|
def begin_db_transaction #:nodoc:
|
@@ -391,13 +401,25 @@ module ActiveRecord
|
|
391
401
|
# Returns an array of indexes for the given table.
|
392
402
|
def indexes(table_name, name = nil) #:nodoc:
|
393
403
|
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", 'SCHEMA').map do |row|
|
404
|
+
sql = <<-SQL
|
405
|
+
SELECT sql
|
406
|
+
FROM sqlite_master
|
407
|
+
WHERE name=#{quote(row['name'])} AND type='index'
|
408
|
+
UNION ALL
|
409
|
+
SELECT sql
|
410
|
+
FROM sqlite_temp_master
|
411
|
+
WHERE name=#{quote(row['name'])} AND type='index'
|
412
|
+
SQL
|
413
|
+
index_sql = exec_query(sql).first['sql']
|
414
|
+
match = /\sWHERE\s+(.+)$/i.match(index_sql)
|
415
|
+
where = match[1] if match
|
394
416
|
IndexDefinition.new(
|
395
417
|
table_name,
|
396
418
|
row['name'],
|
397
419
|
row['unique'] != 0,
|
398
420
|
exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
|
399
421
|
col['name']
|
400
|
-
})
|
422
|
+
}, nil, nil, where)
|
401
423
|
end
|
402
424
|
end
|
403
425
|
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionHandling
|
3
|
+
RAILS_ENV = -> { Rails.env if defined?(Rails) }
|
4
|
+
DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
|
5
|
+
|
3
6
|
# Establishes the connection to the database. Accepts a hash as input where
|
4
7
|
# the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
|
5
8
|
# example for regular databases (MySQL, Postgresql, etc):
|
@@ -32,11 +35,19 @@ module ActiveRecord
|
|
32
35
|
# "postgres://myuser:mypass@localhost/somedatabase"
|
33
36
|
# )
|
34
37
|
#
|
38
|
+
# In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
|
39
|
+
# automatically loads the contents of config/database.yml into it),
|
40
|
+
# a symbol can also be given as argument, representing a key in the
|
41
|
+
# configuration hash:
|
42
|
+
#
|
43
|
+
# ActiveRecord::Base.establish_connection(:production)
|
44
|
+
#
|
35
45
|
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
36
46
|
# may be returned on an error.
|
37
|
-
def establish_connection(spec =
|
38
|
-
|
39
|
-
|
47
|
+
def establish_connection(spec = nil)
|
48
|
+
spec ||= DEFAULT_ENV.call.to_sym
|
49
|
+
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
50
|
+
spec = resolver.spec(spec)
|
40
51
|
|
41
52
|
unless respond_to?(spec.adapter_method)
|
42
53
|
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
@@ -46,6 +57,56 @@ module ActiveRecord
|
|
46
57
|
connection_handler.establish_connection self, spec
|
47
58
|
end
|
48
59
|
|
60
|
+
class MergeAndResolveDefaultUrlConfig # :nodoc:
|
61
|
+
def initialize(raw_configurations, url = ENV['DATABASE_URL'])
|
62
|
+
@raw_config = raw_configurations.dup
|
63
|
+
@url = url
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns fully resolved connection hashes.
|
67
|
+
# Merges connection information from `ENV['DATABASE_URL']` if available.
|
68
|
+
def resolve
|
69
|
+
ConnectionAdapters::ConnectionSpecification::Resolver.new(config).resolve_all
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def config
|
74
|
+
if @url
|
75
|
+
raw_merged_into_default
|
76
|
+
else
|
77
|
+
@raw_config
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw_merged_into_default
|
82
|
+
default = default_url_hash
|
83
|
+
|
84
|
+
@raw_config.each do |env, values|
|
85
|
+
default[env] = values || {}
|
86
|
+
default[env].merge!("url" => @url) { |h, v1, v2| v1 || v2 } if default[env].is_a?(Hash)
|
87
|
+
end
|
88
|
+
default
|
89
|
+
end
|
90
|
+
|
91
|
+
# When the raw configuration is not present and ENV['DATABASE_URL']
|
92
|
+
# is available we return a hash with the connection information in
|
93
|
+
# the connection URL. This hash responds to any string key with
|
94
|
+
# resolved connection information.
|
95
|
+
def default_url_hash
|
96
|
+
if @raw_config.blank?
|
97
|
+
Hash.new do |hash, key|
|
98
|
+
hash[key] = if key.is_a? String
|
99
|
+
ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(@url).to_hash
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
{}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
49
110
|
# Returns the connection currently associated with the class. This can
|
50
111
|
# also be used to "borrow" the connection to do database work unrelated
|
51
112
|
# to any of the specific Active Records.
|
data/lib/active_record/core.rb
CHANGED
@@ -42,9 +42,16 @@ module ActiveRecord
|
|
42
42
|
# 'database' => 'db/production.sqlite3'
|
43
43
|
# }
|
44
44
|
# }
|
45
|
-
|
45
|
+
def self.configurations=(config)
|
46
|
+
@@configurations = ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig.new(config).resolve
|
47
|
+
end
|
46
48
|
self.configurations = {}
|
47
49
|
|
50
|
+
# Returns fully resolved configurations hash
|
51
|
+
def self.configurations
|
52
|
+
@@configurations
|
53
|
+
end
|
54
|
+
|
48
55
|
##
|
49
56
|
# :singleton-method:
|
50
57
|
# Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
|
@@ -69,6 +76,18 @@ module ActiveRecord
|
|
69
76
|
mattr_accessor :timestamped_migrations, instance_writer: false
|
70
77
|
self.timestamped_migrations = true
|
71
78
|
|
79
|
+
##
|
80
|
+
# :singleton-method:
|
81
|
+
# Specify whether schema dump should happen at the end of the
|
82
|
+
# db:migrate rake task. This is true by default, which is useful for the
|
83
|
+
# development environment. This should ideally be false in the production
|
84
|
+
# environment where dumping schema is rarely needed.
|
85
|
+
mattr_accessor :dump_schema_after_migration, instance_writer: false
|
86
|
+
self.dump_schema_after_migration = true
|
87
|
+
|
88
|
+
# :nodoc:
|
89
|
+
mattr_accessor :maintain_test_schema, instance_accessor: false
|
90
|
+
|
72
91
|
def self.disable_implicit_join_references=(value)
|
73
92
|
ActiveSupport::Deprecation.warn("Implicit join references were removed with Rails 4.1." \
|
74
93
|
"Make sure to remove this configuration because it does nothing.")
|
@@ -128,12 +147,12 @@ module ActiveRecord
|
|
128
147
|
# class Post < ActiveRecord::Base
|
129
148
|
# scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
|
130
149
|
# end
|
131
|
-
def arel_table
|
150
|
+
def arel_table # :nodoc:
|
132
151
|
@arel_table ||= Arel::Table.new(table_name, arel_engine)
|
133
152
|
end
|
134
153
|
|
135
154
|
# Returns the Arel engine.
|
136
|
-
def arel_engine
|
155
|
+
def arel_engine # :nodoc:
|
137
156
|
@arel_engine ||=
|
138
157
|
if Base == self || connection_handler.retrieve_connection_pool(self)
|
139
158
|
self
|
@@ -172,9 +191,7 @@ module ActiveRecord
|
|
172
191
|
@column_types = self.class.column_types
|
173
192
|
|
174
193
|
init_internals
|
175
|
-
|
176
|
-
ensure_proper_type
|
177
|
-
populate_with_current_scope_attributes
|
194
|
+
initialize_internals_callback
|
178
195
|
|
179
196
|
# +options+ argument is only needed to make protected_attributes gem easier to hook.
|
180
197
|
# Remove it when we drop support to this gem.
|
@@ -245,16 +262,12 @@ module ActiveRecord
|
|
245
262
|
|
246
263
|
run_callbacks(:initialize) unless _initialize_callbacks.empty?
|
247
264
|
|
248
|
-
@changed_attributes = {}
|
249
|
-
init_changed_attributes
|
250
|
-
|
251
265
|
@aggregation_cache = {}
|
252
266
|
@association_cache = {}
|
253
267
|
@attributes_cache = {}
|
254
268
|
|
255
269
|
@new_record = true
|
256
270
|
|
257
|
-
ensure_proper_type
|
258
271
|
super
|
259
272
|
end
|
260
273
|
|
@@ -271,7 +284,7 @@ module ActiveRecord
|
|
271
284
|
# Post.new.encode_with(coder)
|
272
285
|
# coder # => {"attributes" => {"id" => nil, ... }}
|
273
286
|
def encode_with(coder)
|
274
|
-
coder['attributes'] =
|
287
|
+
coder['attributes'] = attributes_for_coder
|
275
288
|
end
|
276
289
|
|
277
290
|
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
@@ -387,13 +400,10 @@ module ActiveRecord
|
|
387
400
|
end
|
388
401
|
|
389
402
|
def update_attributes_from_transaction_state(transaction_state, depth)
|
390
|
-
if transaction_state && !has_transactional_callbacks?
|
403
|
+
if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
|
391
404
|
unless @reflects_state[depth]
|
392
|
-
if transaction_state.
|
393
|
-
|
394
|
-
elsif transaction_state.rolledback?
|
395
|
-
rolledback!
|
396
|
-
end
|
405
|
+
restore_transaction_record_state if transaction_state.rolledback?
|
406
|
+
clear_transaction_record_state
|
397
407
|
@reflects_state[depth] = true
|
398
408
|
end
|
399
409
|
|
@@ -433,13 +443,7 @@ module ActiveRecord
|
|
433
443
|
@reflects_state = [false]
|
434
444
|
end
|
435
445
|
|
436
|
-
def
|
437
|
-
# Intentionally avoid using #column_defaults since overridden defaults (as is done in
|
438
|
-
# optimistic locking) won't get written unless they get marked as changed
|
439
|
-
self.class.columns.each do |c|
|
440
|
-
attr, orig_value = c.name, c.default
|
441
|
-
changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
|
442
|
-
end
|
446
|
+
def initialize_internals_callback
|
443
447
|
end
|
444
448
|
|
445
449
|
# This method is needed to make protected_attributes gem easier to hook.
|