activerecord 4.0.0 → 4.0.1.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 +326 -3
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/association_relation.rb +18 -0
- data/lib/active_record/associations/association.rb +11 -3
- data/lib/active_record/associations/builder/belongs_to.rb +4 -2
- data/lib/active_record/associations/collection_association.rb +8 -8
- data/lib/active_record/associations/collection_proxy.rb +2 -4
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +2 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -1
- data/lib/active_record/associations/preloader.rb +3 -2
- data/lib/active_record/attribute_methods.rb +26 -2
- data/lib/active_record/attribute_methods/read.rb +15 -9
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +2 -0
- data/lib/active_record/autosave_association.rb +8 -8
- data/lib/active_record/callbacks.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -7
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +12 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -2
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/column.rb +12 -11
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/cast.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +19 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +8 -5
- data/lib/active_record/core.rb +18 -18
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +4 -1
- data/lib/active_record/model_schema.rb +27 -17
- data/lib/active_record/null_relation.rb +1 -5
- data/lib/active_record/persistence.rb +16 -5
- data/lib/active_record/railtie.rb +1 -0
- data/lib/active_record/railties/databases.rake +4 -1
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation.rb +1 -1
- data/lib/active_record/relation/batches.rb +2 -2
- data/lib/active_record/relation/calculations.rb +1 -0
- data/lib/active_record/relation/finder_methods.rb +10 -10
- data/lib/active_record/relation/merger.rb +31 -28
- data/lib/active_record/relation/query_methods.rb +13 -11
- data/lib/active_record/result.rb +15 -1
- data/lib/active_record/sanitization.rb +13 -3
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/tasks/database_tasks.rb +2 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +1 -1
- data/lib/active_record/transactions.rb +5 -5
- data/lib/active_record/validations/uniqueness.rb +2 -2
- data/lib/active_record/version.rb +1 -1
- metadata +10 -9
@@ -13,7 +13,7 @@ module ActiveRecord
|
|
13
13
|
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
14
14
|
end
|
15
15
|
|
16
|
-
attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
|
16
|
+
attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale, :default_function
|
17
17
|
attr_accessor :primary, :coder
|
18
18
|
|
19
19
|
alias :encoded? :coder
|
@@ -27,16 +27,17 @@ module ActiveRecord
|
|
27
27
|
# It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
|
28
28
|
# +null+ determines if this column allows +NULL+ values.
|
29
29
|
def initialize(name, default, sql_type = nil, null = true)
|
30
|
-
@name
|
31
|
-
@sql_type
|
32
|
-
@null
|
33
|
-
@limit
|
34
|
-
@precision
|
35
|
-
@scale
|
36
|
-
@type
|
37
|
-
@default
|
38
|
-
@
|
39
|
-
@
|
30
|
+
@name = name
|
31
|
+
@sql_type = sql_type
|
32
|
+
@null = null
|
33
|
+
@limit = extract_limit(sql_type)
|
34
|
+
@precision = extract_precision(sql_type)
|
35
|
+
@scale = extract_scale(sql_type)
|
36
|
+
@type = simplified_type(sql_type)
|
37
|
+
@default = extract_default(default)
|
38
|
+
@default_function = nil
|
39
|
+
@primary = nil
|
40
|
+
@coder = nil
|
40
41
|
end
|
41
42
|
|
42
43
|
# Returns +true+ if the column is either of type string or text.
|
@@ -213,9 +213,11 @@ module ActiveRecord
|
|
213
213
|
|
214
214
|
# Executes the SQL statement in the context of this connection.
|
215
215
|
def execute(sql, name = nil)
|
216
|
-
|
217
|
-
|
218
|
-
|
216
|
+
if @connection
|
217
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
218
|
+
# made since we established the connection
|
219
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
220
|
+
end
|
219
221
|
|
220
222
|
super
|
221
223
|
end
|
@@ -268,6 +270,10 @@ module ActiveRecord
|
|
268
270
|
def version
|
269
271
|
@version ||= @connection.info[:version].scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
|
270
272
|
end
|
273
|
+
|
274
|
+
def set_field_encoding field_name
|
275
|
+
field_name
|
276
|
+
end
|
271
277
|
end
|
272
278
|
end
|
273
279
|
end
|
@@ -279,11 +279,7 @@ module ActiveRecord
|
|
279
279
|
end
|
280
280
|
|
281
281
|
def exec_query(sql, name = 'SQL', binds = [])
|
282
|
-
|
283
|
-
# always be empty, since the bind variables will have been already
|
284
|
-
# substituted and removed from binds by BindVisitor, so this will
|
285
|
-
# effectively disable prepared statement usage completely.
|
286
|
-
if binds.empty?
|
282
|
+
if without_prepared_statement?(binds)
|
287
283
|
result_set, affected_rows = exec_without_stmt(sql, name)
|
288
284
|
else
|
289
285
|
result_set, affected_rows = exec_stmt(sql, name, binds)
|
@@ -393,6 +389,14 @@ module ActiveRecord
|
|
393
389
|
TYPES[new] = TYPES[old]
|
394
390
|
end
|
395
391
|
|
392
|
+
def self.find_type(field)
|
393
|
+
if field.type == Mysql::Field::TYPE_TINY && field.length > 1
|
394
|
+
TYPES[Mysql::Field::TYPE_LONG]
|
395
|
+
else
|
396
|
+
TYPES.fetch(field.type) { Fields::Identity.new }
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
396
400
|
register_type Mysql::Field::TYPE_TINY, Fields::Boolean.new
|
397
401
|
register_type Mysql::Field::TYPE_LONG, Fields::Integer.new
|
398
402
|
alias_type Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_LONG
|
@@ -425,9 +429,7 @@ module ActiveRecord
|
|
425
429
|
if field.decimals > 0
|
426
430
|
types[field.name] = Fields::Decimal.new
|
427
431
|
else
|
428
|
-
types[field.name] = Fields
|
429
|
-
Fields::Identity.new
|
430
|
-
}
|
432
|
+
types[field.name] = Fields.find_type field
|
431
433
|
end
|
432
434
|
}
|
433
435
|
result_set = ActiveRecord::Result.new(types.keys, result.to_a, types)
|
@@ -501,12 +503,12 @@ module ActiveRecord
|
|
501
503
|
cols = cache[:cols] ||= metadata.fetch_fields.map { |field|
|
502
504
|
field.name
|
503
505
|
}
|
506
|
+
metadata.free
|
504
507
|
end
|
505
508
|
|
506
509
|
result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
|
507
510
|
affected_rows = stmt.affected_rows
|
508
511
|
|
509
|
-
stmt.result_metadata.free if cols
|
510
512
|
stmt.free_result
|
511
513
|
stmt.close if binds.empty?
|
512
514
|
|
@@ -553,6 +555,14 @@ module ActiveRecord
|
|
553
555
|
def version
|
554
556
|
@version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
|
555
557
|
end
|
558
|
+
|
559
|
+
def set_field_encoding field_name
|
560
|
+
field_name.force_encoding(client_encoding)
|
561
|
+
if internal_enc = Encoding.default_internal
|
562
|
+
field_name = field_name.encoding(internal_enc)
|
563
|
+
end
|
564
|
+
field_name
|
565
|
+
end
|
556
566
|
end
|
557
567
|
end
|
558
568
|
end
|
@@ -135,11 +135,12 @@ module ActiveRecord
|
|
135
135
|
|
136
136
|
def exec_query(sql, name = 'SQL', binds = [])
|
137
137
|
log(sql, name, binds) do
|
138
|
-
result = binds
|
139
|
-
|
138
|
+
result = without_prepared_statement?(binds) ? exec_no_cache(sql, binds) :
|
139
|
+
exec_cache(sql, binds)
|
140
140
|
|
141
141
|
types = {}
|
142
|
-
result.fields
|
142
|
+
fields = result.fields
|
143
|
+
fields.each_with_index do |fname, i|
|
143
144
|
ftype = result.ftype i
|
144
145
|
fmod = result.fmod i
|
145
146
|
types[fname] = OID::TYPE_MAP.fetch(ftype, fmod) { |oid, mod|
|
@@ -148,7 +149,7 @@ module ActiveRecord
|
|
148
149
|
}
|
149
150
|
end
|
150
151
|
|
151
|
-
ret = ActiveRecord::Result.new(
|
152
|
+
ret = ActiveRecord::Result.new(fields, result.values, types)
|
152
153
|
result.clear
|
153
154
|
return ret
|
154
155
|
end
|
@@ -156,8 +157,8 @@ module ActiveRecord
|
|
156
157
|
|
157
158
|
def exec_delete(sql, name = 'SQL', binds = [])
|
158
159
|
log(sql, name, binds) do
|
159
|
-
result = binds
|
160
|
-
|
160
|
+
result = without_prepared_statement?(binds) ? exec_no_cache(sql, binds) :
|
161
|
+
exec_cache(sql, binds)
|
161
162
|
affected = result.cmd_tuples
|
162
163
|
result.clear
|
163
164
|
affected
|
@@ -38,12 +38,17 @@ module ActiveRecord
|
|
38
38
|
class Money < Type
|
39
39
|
def type_cast(value)
|
40
40
|
return if value.nil?
|
41
|
+
return value unless String === value
|
41
42
|
|
42
43
|
# Because money output is formatted according to the locale, there are two
|
43
44
|
# cases to consider (note the decimal separators):
|
44
45
|
# (1) $12,345,678.12
|
45
46
|
# (2) $12.345.678,12
|
47
|
+
# Negative values are represented as follows:
|
48
|
+
# (3) -$2.55
|
49
|
+
# (4) ($2.55)
|
46
50
|
|
51
|
+
value.sub!(/^\((.+)\)$/, '-\1') # (4)
|
47
52
|
case value
|
48
53
|
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
49
54
|
value.gsub!(/[^-\d.]/, '')
|
@@ -30,6 +30,7 @@ module ActiveRecord
|
|
30
30
|
when Array
|
31
31
|
case sql_type
|
32
32
|
when 'point' then super(PostgreSQLColumn.point_to_string(value))
|
33
|
+
when 'json' then super(PostgreSQLColumn.json_to_string(value))
|
33
34
|
else
|
34
35
|
if column.array
|
35
36
|
"'#{PostgreSQLColumn.array_to_string(value, column, self).gsub(/'/, "''")}'"
|
@@ -98,6 +99,7 @@ module ActiveRecord
|
|
98
99
|
when Array
|
99
100
|
case column.sql_type
|
100
101
|
when 'point' then PostgreSQLColumn.point_to_string(value)
|
102
|
+
when 'json' then PostgreSQLColumn.json_to_string(value)
|
101
103
|
else
|
102
104
|
return super(value, column) unless column.array
|
103
105
|
PostgreSQLColumn.array_to_string(value, column, self)
|
@@ -321,6 +321,7 @@ module ActiveRecord
|
|
321
321
|
result = query(<<-end_sql, 'SCHEMA')[0]
|
322
322
|
SELECT attr.attname,
|
323
323
|
CASE
|
324
|
+
WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL
|
324
325
|
WHEN split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2) ~ '.' THEN
|
325
326
|
substr(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2),
|
326
327
|
strpos(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2), '.')+1)
|
@@ -332,7 +333,7 @@ module ActiveRecord
|
|
332
333
|
JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])
|
333
334
|
WHERE t.oid = '#{quote_table_name(table)}'::regclass
|
334
335
|
AND cons.contype = 'p'
|
335
|
-
AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval'
|
336
|
+
AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
|
336
337
|
end_sql
|
337
338
|
end
|
338
339
|
|
@@ -383,8 +384,9 @@ module ActiveRecord
|
|
383
384
|
def change_column(table_name, column_name, type, options = {})
|
384
385
|
clear_cache!
|
385
386
|
quoted_table_name = quote_table_name(table_name)
|
386
|
-
|
387
|
-
|
387
|
+
sql_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
|
388
|
+
sql_type << "[]" if options[:array]
|
389
|
+
execute "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{sql_type}"
|
388
390
|
|
389
391
|
change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
|
390
392
|
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
@@ -466,14 +468,9 @@ module ActiveRecord
|
|
466
468
|
end
|
467
469
|
end
|
468
470
|
|
469
|
-
# Returns a SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
|
470
|
-
#
|
471
471
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
472
472
|
# requires that the ORDER BY include the distinct column.
|
473
|
-
|
474
|
-
# distinct("posts.id", ["posts.created_at desc"])
|
475
|
-
# # => "DISTINCT posts.id, posts.created_at AS alias_0"
|
476
|
-
def distinct(columns, orders) #:nodoc:
|
473
|
+
def columns_for_distinct(columns, orders) #:nodoc:
|
477
474
|
order_columns = orders.map{ |s|
|
478
475
|
# Convert Arel node to string
|
479
476
|
s = s.to_sql unless s.is_a?(String)
|
@@ -481,7 +478,7 @@ module ActiveRecord
|
|
481
478
|
s.gsub(/\s+(ASC|DESC)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '')
|
482
479
|
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
483
480
|
|
484
|
-
[super].
|
481
|
+
[super, *order_columns].join(', ')
|
485
482
|
end
|
486
483
|
end
|
487
484
|
end
|
@@ -49,13 +49,17 @@ module ActiveRecord
|
|
49
49
|
# Instantiates a new PostgreSQL column definition in a table.
|
50
50
|
def initialize(name, default, oid_type, sql_type = nil, null = true)
|
51
51
|
@oid_type = oid_type
|
52
|
+
default_value = self.class.extract_value_from_default(default)
|
53
|
+
|
52
54
|
if sql_type =~ /\[\]$/
|
53
55
|
@array = true
|
54
|
-
super(name,
|
56
|
+
super(name, default_value, sql_type[0..sql_type.length - 3], null)
|
55
57
|
else
|
56
58
|
@array = false
|
57
|
-
super(name,
|
59
|
+
super(name, default_value, sql_type, null)
|
58
60
|
end
|
61
|
+
|
62
|
+
@default_function = default if has_default_function?(default_value, default)
|
59
63
|
end
|
60
64
|
|
61
65
|
# :stopdoc:
|
@@ -138,6 +142,10 @@ module ActiveRecord
|
|
138
142
|
|
139
143
|
private
|
140
144
|
|
145
|
+
def has_default_function?(default_value, default)
|
146
|
+
!default_value && (%r{\w+(.*)} === default)
|
147
|
+
end
|
148
|
+
|
141
149
|
def extract_limit(sql_type)
|
142
150
|
case sql_type
|
143
151
|
when /^bigint/i; 8
|
@@ -374,15 +382,11 @@ module ActiveRecord
|
|
374
382
|
self
|
375
383
|
end
|
376
384
|
|
377
|
-
def xml(options = {})
|
378
|
-
column(args[0], :text, options)
|
379
|
-
end
|
380
|
-
|
381
385
|
private
|
382
386
|
|
383
|
-
|
384
|
-
|
385
|
-
|
387
|
+
def create_column_definition(name, type)
|
388
|
+
ColumnDefinition.new name, type
|
389
|
+
end
|
386
390
|
end
|
387
391
|
|
388
392
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
@@ -436,6 +440,7 @@ module ActiveRecord
|
|
436
440
|
def prepare_column_options(column, types)
|
437
441
|
spec = super
|
438
442
|
spec[:array] = 'true' if column.respond_to?(:array) && column.array
|
443
|
+
spec[:default] = "\"#{column.default_function}\"" if column.default_function
|
439
444
|
spec
|
440
445
|
end
|
441
446
|
|
@@ -528,6 +533,7 @@ module ActiveRecord
|
|
528
533
|
super(connection, logger)
|
529
534
|
|
530
535
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
536
|
+
@prepared_statements = true
|
531
537
|
@visitor = Arel::Visitors::PostgreSQL.new self
|
532
538
|
else
|
533
539
|
@visitor = unprepared_visitor
|
@@ -623,9 +629,9 @@ module ActiveRecord
|
|
623
629
|
true
|
624
630
|
end
|
625
631
|
|
626
|
-
# Returns true if pg > 9.
|
632
|
+
# Returns true if pg > 9.1
|
627
633
|
def supports_extensions?
|
628
|
-
postgresql_version >=
|
634
|
+
postgresql_version >= 90100
|
629
635
|
end
|
630
636
|
|
631
637
|
# Range datatypes weren't introduced until PostgreSQL 9.2
|
@@ -647,9 +653,9 @@ module ActiveRecord
|
|
647
653
|
|
648
654
|
def extension_enabled?(name)
|
649
655
|
if supports_extensions?
|
650
|
-
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL)",
|
656
|
+
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
|
651
657
|
'SCHEMA'
|
652
|
-
res.column_types['
|
658
|
+
res.column_types['enabled'].type_cast res.rows.first.first
|
653
659
|
end
|
654
660
|
end
|
655
661
|
|
@@ -17,12 +17,14 @@ module ActiveRecord
|
|
17
17
|
# Allow database path relative to Rails.root, but only if
|
18
18
|
# the database path is not the special path that tells
|
19
19
|
# Sqlite to build a database only in memory.
|
20
|
-
if
|
21
|
-
config[:database] = File.expand_path(config[:database], Rails.root)
|
20
|
+
if ':memory:' != config[:database]
|
21
|
+
config[:database] = File.expand_path(config[:database], Rails.root) if defined?(Rails.root)
|
22
|
+
dirname = File.dirname(config[:database])
|
23
|
+
Dir.mkdir(dirname) unless File.directory?(dirname)
|
22
24
|
end
|
23
25
|
|
24
26
|
db = SQLite3::Database.new(
|
25
|
-
config[:database],
|
27
|
+
config[:database].to_s,
|
26
28
|
:results_as_hash => true
|
27
29
|
)
|
28
30
|
|
@@ -111,6 +113,7 @@ module ActiveRecord
|
|
111
113
|
@config = config
|
112
114
|
|
113
115
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
116
|
+
@prepared_statements = true
|
114
117
|
@visitor = Arel::Visitors::SQLite.new self
|
115
118
|
else
|
116
119
|
@visitor = unprepared_visitor
|
@@ -291,8 +294,8 @@ module ActiveRecord
|
|
291
294
|
def exec_query(sql, name = nil, binds = [])
|
292
295
|
log(sql, name, binds) do
|
293
296
|
|
294
|
-
# Don't cache statements
|
295
|
-
if binds
|
297
|
+
# Don't cache statements if they are not prepared
|
298
|
+
if without_prepared_statement?(binds)
|
296
299
|
stmt = @connection.prepare(sql)
|
297
300
|
cols = stmt.columns
|
298
301
|
records = stmt.to_a
|
data/lib/active_record/core.rb
CHANGED
@@ -91,20 +91,8 @@ module ActiveRecord
|
|
91
91
|
end
|
92
92
|
|
93
93
|
module ClassMethods
|
94
|
-
def inherited(child_class) #:nodoc:
|
95
|
-
child_class.initialize_generated_modules
|
96
|
-
super
|
97
|
-
end
|
98
|
-
|
99
94
|
def initialize_generated_modules
|
100
|
-
|
101
|
-
|
102
|
-
# force attribute methods to be higher in inheritance hierarchy than other generated methods
|
103
|
-
generated_attribute_methods.const_set(:AttrNames, Module.new {
|
104
|
-
def self.const_missing(name)
|
105
|
-
const_set(name, [name.to_s.sub(/ATTR_/, '')].pack('h*').freeze)
|
106
|
-
end
|
107
|
-
})
|
95
|
+
super
|
108
96
|
|
109
97
|
generated_feature_methods
|
110
98
|
end
|
@@ -123,6 +111,8 @@ module ActiveRecord
|
|
123
111
|
super
|
124
112
|
elsif abstract_class?
|
125
113
|
"#{super}(abstract)"
|
114
|
+
elsif !connected?
|
115
|
+
"#{super}(no database connection)"
|
126
116
|
elsif table_exists?
|
127
117
|
attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
|
128
118
|
"#{super}(#{attr_list})"
|
@@ -153,7 +143,7 @@ module ActiveRecord
|
|
153
143
|
else
|
154
144
|
superclass.arel_engine
|
155
145
|
end
|
156
|
-
|
146
|
+
end
|
157
147
|
end
|
158
148
|
|
159
149
|
private
|
@@ -177,19 +167,22 @@ module ActiveRecord
|
|
177
167
|
# ==== Example:
|
178
168
|
# # Instantiates a single new object
|
179
169
|
# User.new(first_name: 'Jamie')
|
180
|
-
def initialize(attributes = nil)
|
170
|
+
def initialize(attributes = nil, options = {})
|
181
171
|
defaults = self.class.column_defaults.dup
|
182
172
|
defaults.each { |k, v| defaults[k] = v.dup if v.duplicable? }
|
183
173
|
|
184
174
|
@attributes = self.class.initialize_attributes(defaults)
|
185
|
-
@
|
175
|
+
@column_types_override = nil
|
176
|
+
@column_types = self.class.column_types
|
186
177
|
|
187
178
|
init_internals
|
188
179
|
init_changed_attributes
|
189
180
|
ensure_proper_type
|
190
181
|
populate_with_current_scope_attributes
|
191
182
|
|
192
|
-
|
183
|
+
# +options+ argument is only needed to make protected_attributes gem easier to hook.
|
184
|
+
# Remove it when we drop support to this gem.
|
185
|
+
init_attributes(attributes, options) if attributes
|
193
186
|
|
194
187
|
yield self if block_given?
|
195
188
|
run_callbacks :initialize unless _initialize_callbacks.empty?
|
@@ -207,7 +200,8 @@ module ActiveRecord
|
|
207
200
|
# post.title # => 'hello world'
|
208
201
|
def init_with(coder)
|
209
202
|
@attributes = self.class.initialize_attributes(coder['attributes'])
|
210
|
-
@
|
203
|
+
@column_types_override = coder['column_types']
|
204
|
+
@column_types = self.class.column_types
|
211
205
|
|
212
206
|
init_internals
|
213
207
|
|
@@ -459,5 +453,11 @@ module ActiveRecord
|
|
459
453
|
@changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
|
460
454
|
end
|
461
455
|
end
|
456
|
+
|
457
|
+
# This method is needed to make protected_attributes gem easier to hook.
|
458
|
+
# Remove it when we drop support to this gem.
|
459
|
+
def init_attributes(attributes, options)
|
460
|
+
assign_attributes(attributes)
|
461
|
+
end
|
462
462
|
end
|
463
463
|
end
|