activerecord 4.2.0 → 4.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -1
  3. data/lib/active_record.rb +3 -0
  4. data/lib/active_record/aggregations.rb +6 -3
  5. data/lib/active_record/association_relation.rb +13 -0
  6. data/lib/active_record/associations.rb +5 -4
  7. data/lib/active_record/associations/association.rb +15 -3
  8. data/lib/active_record/associations/association_scope.rb +1 -0
  9. data/lib/active_record/associations/belongs_to_association.rb +13 -5
  10. data/lib/active_record/associations/builder/association.rb +1 -1
  11. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -4
  13. data/lib/active_record/associations/collection_association.rb +35 -15
  14. data/lib/active_record/associations/collection_proxy.rb +15 -9
  15. data/lib/active_record/associations/foreign_association.rb +11 -0
  16. data/lib/active_record/associations/has_many_association.rb +30 -15
  17. data/lib/active_record/associations/has_many_through_association.rb +11 -2
  18. data/lib/active_record/associations/has_one_association.rb +1 -0
  19. data/lib/active_record/associations/join_dependency.rb +8 -2
  20. data/lib/active_record/associations/join_dependency/join_association.rb +7 -1
  21. data/lib/active_record/associations/preloader.rb +4 -4
  22. data/lib/active_record/associations/preloader/association.rb +5 -1
  23. data/lib/active_record/associations/singular_association.rb +2 -8
  24. data/lib/active_record/associations/through_association.rb +11 -6
  25. data/lib/active_record/attribute.rb +15 -1
  26. data/lib/active_record/attribute_assignment.rb +2 -2
  27. data/lib/active_record/attribute_methods.rb +4 -8
  28. data/lib/active_record/attribute_methods/before_type_cast.rb +5 -0
  29. data/lib/active_record/attribute_methods/dirty.rb +14 -4
  30. data/lib/active_record/attribute_methods/time_zone_conversion.rb +5 -1
  31. data/lib/active_record/attribute_methods/write.rb +1 -1
  32. data/lib/active_record/attribute_set.rb +4 -0
  33. data/lib/active_record/attribute_set/builder.rb +32 -12
  34. data/lib/active_record/attributes.rb +8 -0
  35. data/lib/active_record/autosave_association.rb +24 -9
  36. data/lib/active_record/base.rb +4 -5
  37. data/lib/active_record/callbacks.rb +1 -1
  38. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +12 -6
  39. data/lib/active_record/connection_adapters/abstract/database_statements.rb +23 -3
  40. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -0
  42. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  43. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -16
  44. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +87 -24
  45. data/lib/active_record/connection_adapters/abstract/transaction.rb +2 -6
  46. data/lib/active_record/connection_adapters/abstract_adapter.rb +25 -7
  47. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -10
  48. data/lib/active_record/connection_adapters/column.rb +2 -2
  49. data/lib/active_record/connection_adapters/mysql2_adapter.rb +7 -21
  50. data/lib/active_record/connection_adapters/mysql_adapter.rb +10 -3
  51. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  52. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -1
  53. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -0
  54. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -0
  55. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
  56. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -1
  57. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -0
  58. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
  59. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +3 -3
  60. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +21 -13
  61. data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -12
  62. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -28
  63. data/lib/active_record/connection_handling.rb +1 -1
  64. data/lib/active_record/core.rb +28 -15
  65. data/lib/active_record/counter_cache.rb +1 -1
  66. data/lib/active_record/enum.rb +2 -3
  67. data/lib/active_record/errors.rb +6 -5
  68. data/lib/active_record/explain_subscriber.rb +1 -1
  69. data/lib/active_record/fixtures.rb +9 -7
  70. data/lib/active_record/gem_version.rb +1 -1
  71. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  72. data/lib/active_record/locking/optimistic.rb +16 -14
  73. data/lib/active_record/migration.rb +38 -10
  74. data/lib/active_record/model_schema.rb +4 -2
  75. data/lib/active_record/nested_attributes.rb +13 -3
  76. data/lib/active_record/no_touching.rb +1 -1
  77. data/lib/active_record/persistence.rb +7 -4
  78. data/lib/active_record/railtie.rb +5 -3
  79. data/lib/active_record/railties/databases.rake +17 -24
  80. data/lib/active_record/reflection.rb +40 -28
  81. data/lib/active_record/relation.rb +3 -2
  82. data/lib/active_record/relation/calculations.rb +10 -3
  83. data/lib/active_record/relation/delegation.rb +1 -1
  84. data/lib/active_record/relation/finder_methods.rb +4 -16
  85. data/lib/active_record/relation/merger.rb +24 -1
  86. data/lib/active_record/relation/predicate_builder.rb +32 -3
  87. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -2
  88. data/lib/active_record/relation/query_methods.rb +29 -27
  89. data/lib/active_record/relation/spawn_methods.rb +7 -3
  90. data/lib/active_record/schema_dumper.rb +1 -1
  91. data/lib/active_record/schema_migration.rb +1 -4
  92. data/lib/active_record/scoping/default.rb +1 -0
  93. data/lib/active_record/tasks/database_tasks.rb +5 -2
  94. data/lib/active_record/tasks/mysql_database_tasks.rb +30 -16
  95. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -8
  96. data/lib/active_record/transactions.rb +21 -11
  97. data/lib/active_record/type/boolean.rb +1 -0
  98. data/lib/active_record/type/date.rb +4 -0
  99. data/lib/active_record/type/date_time.rb +14 -3
  100. data/lib/active_record/type/decimal.rb +27 -3
  101. data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
  102. data/lib/active_record/type/integer.rb +9 -5
  103. data/lib/active_record/type/numeric.rb +1 -1
  104. data/lib/active_record/type/serialized.rb +7 -1
  105. data/lib/active_record/type/string.rb +4 -0
  106. data/lib/active_record/type/value.rb +9 -0
  107. data/lib/active_record/validations/uniqueness.rb +16 -6
  108. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -3
  109. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -6
  110. metadata +9 -7
@@ -5,6 +5,15 @@ module ActiveRecord
5
5
  class DateTime < Type::DateTime # :nodoc:
6
6
  include Infinity
7
7
 
8
+ def type_cast_for_database(value)
9
+ if has_precision? && value.acts_like?(:time) && value.year <= 0
10
+ bce_year = format("%04d", -value.year + 1)
11
+ super.sub(/^-?\d+/, bce_year) + " BC"
12
+ else
13
+ super
14
+ end
15
+ end
16
+
8
17
  def cast_value(value)
9
18
  if value.is_a?(::String)
10
19
  case value
@@ -7,7 +7,9 @@ module ActiveRecord
7
7
  :enum
8
8
  end
9
9
 
10
- def type_cast(value)
10
+ private
11
+
12
+ def cast_value(value)
11
13
  value.to_s
12
14
  end
13
15
  end
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
 
12
12
  def type_cast_from_database(value)
13
13
  if value.is_a?(::String)
14
- ::ActiveSupport::JSON.decode(value)
14
+ ::ActiveSupport::JSON.decode(value) rescue nil
15
15
  else
16
16
  super
17
17
  end
@@ -8,6 +8,10 @@ module ActiveRecord
8
8
  def initialize(type)
9
9
  @type = type
10
10
  end
11
+
12
+ def text?
13
+ false
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -15,11 +15,11 @@ module ActiveRecord
15
15
  def run(records)
16
16
  nodes = records.reject { |row| @store.key? row['oid'].to_i }
17
17
  mapped, nodes = nodes.partition { |row| @store.key? row['typname'] }
18
- ranges, nodes = nodes.partition { |row| row['typtype'] == 'r' }
19
- enums, nodes = nodes.partition { |row| row['typtype'] == 'e' }
20
- domains, nodes = nodes.partition { |row| row['typtype'] == 'd' }
21
- arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
22
- composites, nodes = nodes.partition { |row| row['typelem'] != '0' }
18
+ ranges, nodes = nodes.partition { |row| row['typtype'] == 'r'.freeze }
19
+ enums, nodes = nodes.partition { |row| row['typtype'] == 'e'.freeze }
20
+ domains, nodes = nodes.partition { |row| row['typtype'] == 'd'.freeze }
21
+ arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in'.freeze }
22
+ composites, nodes = nodes.partition { |row| row['typelem'].to_i != 0 }
23
23
 
24
24
  mapped.each { |row| register_mapped_type(row) }
25
25
  enums.each { |row| register_enum_type(row) }
@@ -29,6 +29,18 @@ module ActiveRecord
29
29
  composites.each { |row| register_composite_type(row) }
30
30
  end
31
31
 
32
+ def query_conditions_for_initial_load(type_map)
33
+ known_type_names = type_map.keys.map { |n| "'#{n}'" }
34
+ known_type_types = %w('r' 'e' 'd')
35
+ <<-SQL % [known_type_names.join(", "), known_type_types.join(", ")]
36
+ WHERE
37
+ t.typname IN (%s)
38
+ OR t.typtype IN (%s)
39
+ OR t.typinput = 'array_in(cstring,oid,integer)'::regprocedure
40
+ OR t.typelem != 0
41
+ SQL
42
+ end
43
+
32
44
  private
33
45
  def register_mapped_type(row)
34
46
  alias_type row['oid'], row['typname']
@@ -76,15 +76,15 @@ module ActiveRecord
76
76
  column(name, :point, options)
77
77
  end
78
78
 
79
- def bit(name, options)
79
+ def bit(name, options = {})
80
80
  column(name, :bit, options)
81
81
  end
82
82
 
83
- def bit_varying(name, options)
83
+ def bit_varying(name, options = {})
84
84
  column(name, :bit_varying, options)
85
85
  end
86
86
 
87
- def money(name, options)
87
+ def money(name, options = {})
88
88
  column(name, :money, options)
89
89
  end
90
90
  end
@@ -86,7 +86,7 @@ module ActiveRecord
86
86
  execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
87
87
  end
88
88
 
89
- # Returns the list of all tables in the schema search path or a specified schema.
89
+ # Returns the list of all tables in the schema search path.
90
90
  def tables(name = nil)
91
91
  query(<<-SQL, 'SCHEMA').map { |row| row[0] }
92
92
  SELECT tablename
@@ -95,6 +95,16 @@ module ActiveRecord
95
95
  SQL
96
96
  end
97
97
 
98
+ def data_sources # :nodoc
99
+ select_values(<<-SQL, 'SCHEMA')
100
+ SELECT c.relname
101
+ FROM pg_class c
102
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
103
+ WHERE c.relkind IN ('r', 'v','m') -- (r)elation/table, (v)iew, (m)aterialized view
104
+ AND n.nspname = ANY (current_schemas(false))
105
+ SQL
106
+ end
107
+
98
108
  # Returns true if table exists.
99
109
  # If the schema is not specified as part of +name+ then it will only find tables within
100
110
  # the current schema search path (regardless of permissions to access tables in other schemas)
@@ -111,6 +121,7 @@ module ActiveRecord
111
121
  AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'}
112
122
  SQL
113
123
  end
124
+ alias data_source_exists? table_exists?
114
125
 
115
126
  def drop_table(table_name, options = {})
116
127
  execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
@@ -386,15 +397,15 @@ module ActiveRecord
386
397
 
387
398
  # Returns just a table's primary key
388
399
  def primary_key(table)
389
- row = exec_query(<<-end_sql, 'SCHEMA').rows.first
400
+ pks = exec_query(<<-end_sql, 'SCHEMA').rows
390
401
  SELECT attr.attname
391
402
  FROM pg_attribute attr
392
- INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1]
403
+ INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey)
393
404
  WHERE cons.contype = 'p'
394
405
  AND cons.conrelid = '#{quote_table_name(table)}'::regclass
395
406
  end_sql
396
-
397
- row && row.first
407
+ return nil unless pks.count == 1
408
+ pks[0][0]
398
409
  end
399
410
 
400
411
  # Renames a table.
@@ -418,9 +429,7 @@ module ActiveRecord
418
429
  rename_table_indexes(table_name, new_name)
419
430
  end
420
431
 
421
- # Adds a new column to the named table.
422
- # See TableDefinition#column for details of the options you can use.
423
- def add_column(table_name, column_name, type, options = {})
432
+ def add_column(table_name, column_name, type, options = {}) #:nodoc:
424
433
  clear_cache!
425
434
  super
426
435
  end
@@ -468,7 +477,7 @@ module ActiveRecord
468
477
  end
469
478
 
470
479
  # Renames a column in a table.
471
- def rename_column(table_name, column_name, new_column_name)
480
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
472
481
  clear_cache!
473
482
  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
474
483
  rename_column_indexes(table_name, column_name, new_column_name)
@@ -484,9 +493,8 @@ module ActiveRecord
484
493
  end
485
494
 
486
495
  def rename_index(table_name, old_name, new_name)
487
- if new_name.length > allowed_index_name_length
488
- raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
489
- end
496
+ validate_index_length!(table_name, new_name)
497
+
490
498
  execute "ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
491
499
  end
492
500
 
@@ -555,7 +563,7 @@ module ActiveRecord
555
563
  when 1, 2; 'smallint'
556
564
  when 3, 4; 'integer'
557
565
  when 5..8; 'bigint'
558
- else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
566
+ else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead.")
559
567
  end
560
568
  when 'datetime'
561
569
  return super unless precision
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
  # <tt>SET client_min_messages TO <min_messages></tt> call on the connection.
65
65
  # * <tt>:variables</tt> - An optional hash of additional parameters that
66
66
  # will be used in <tt>SET SESSION key = val</tt> calls on the connection.
67
- # * <tt>:insert_returning</tt> - An optional boolean to control the use or <tt>RETURNING</tt> for <tt>INSERT</tt> statements
67
+ # * <tt>:insert_returning</tt> - An optional boolean to control the use of <tt>RETURNING</tt> for <tt>INSERT</tt> statements
68
68
  # defaults to true.
69
69
  #
70
70
  # Any further options are used as connection parameters to libpq. See
@@ -308,12 +308,8 @@ module ActiveRecord
308
308
  true
309
309
  end
310
310
 
311
- # Enable standard-conforming strings if available.
312
311
  def set_standard_conforming_strings
313
- old, self.client_min_messages = client_min_messages, 'panic'
314
- execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil
315
- ensure
316
- self.client_min_messages = old
312
+ execute('SET standard_conforming_strings = on', 'SCHEMA')
317
313
  end
318
314
 
319
315
  def supports_ddl_transactions?
@@ -445,8 +441,8 @@ module ActiveRecord
445
441
 
446
442
  def initialize_type_map(m) # :nodoc:
447
443
  register_class_with_limit m, 'int2', OID::Integer
448
- m.alias_type 'int4', 'int2'
449
- m.alias_type 'int8', 'int2'
444
+ register_class_with_limit m, 'int4', OID::Integer
445
+ register_class_with_limit m, 'int8', OID::Integer
450
446
  m.alias_type 'oid', 'int2'
451
447
  m.register_type 'float4', OID::Float.new
452
448
  m.alias_type 'float8', 'float4'
@@ -556,6 +552,8 @@ module ActiveRecord
556
552
  end
557
553
 
558
554
  def load_additional_types(type_map, oids = nil) # :nodoc:
555
+ initializer = OID::TypeMapInitializer.new(type_map)
556
+
559
557
  if supports_ranges?
560
558
  query = <<-SQL
561
559
  SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
@@ -571,11 +569,13 @@ module ActiveRecord
571
569
 
572
570
  if oids
573
571
  query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
572
+ else
573
+ query += initializer.query_conditions_for_initial_load(type_map)
574
574
  end
575
575
 
576
- initializer = OID::TypeMapInitializer.new(type_map)
577
- records = execute(query, 'SCHEMA')
578
- initializer.run(records)
576
+ execute_and_clear(query, 'SCHEMA', []) do |records|
577
+ initializer.run(records)
578
+ end
579
579
  end
580
580
 
581
581
  FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
@@ -673,7 +673,7 @@ module ActiveRecord
673
673
  self.client_min_messages = @config[:min_messages] || 'warning'
674
674
  self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
675
675
 
676
- # Use standard-conforming strings if available so we don't have to do the E'...' dance.
676
+ # Use standard-conforming strings so we don't have to do the E'...' dance.
677
677
  set_standard_conforming_strings
678
678
 
679
679
  # If using Active Record's time zone support configure the connection to return
@@ -50,16 +50,6 @@ module ActiveRecord
50
50
  end
51
51
  end
52
52
 
53
- class SQLite3String < Type::String # :nodoc:
54
- def type_cast_for_database(value)
55
- if value.is_a?(::String) && value.encoding == Encoding::ASCII_8BIT
56
- value.encode(Encoding::UTF_8)
57
- else
58
- super
59
- end
60
- end
61
- end
62
-
63
53
  # The SQLite3 adapter works SQLite 3.6.16 or newer
64
54
  # with the sqlite3-ruby drivers (available as gem from https://rubygems.org/gems/sqlite3).
65
55
  #
@@ -84,18 +74,6 @@ module ActiveRecord
84
74
  boolean: { name: "boolean" }
85
75
  }
86
76
 
87
- class Version
88
- include Comparable
89
-
90
- def initialize(version_string)
91
- @version = version_string.split('.').map { |v| v.to_i }
92
- end
93
-
94
- def <=>(version_string)
95
- @version <=> version_string.split('.').map { |v| v.to_i }
96
- end
97
- end
98
-
99
77
  class StatementPool < ConnectionAdapters::StatementPool
100
78
  def initialize(connection, max)
101
79
  super
@@ -239,6 +217,12 @@ module ActiveRecord
239
217
  case value
240
218
  when BigDecimal
241
219
  value.to_f
220
+ when String
221
+ if value.encoding == Encoding::ASCII_8BIT
222
+ super(value.encode(Encoding::UTF_8))
223
+ else
224
+ super
225
+ end
242
226
  else
243
227
  super
244
228
  end
@@ -361,7 +345,7 @@ module ActiveRecord
361
345
  log('commit transaction',nil) { @connection.commit }
362
346
  end
363
347
 
364
- def rollback_db_transaction #:nodoc:
348
+ def exec_rollback_db_transaction #:nodoc:
365
349
  log('rollback transaction',nil) { @connection.rollback }
366
350
  end
367
351
 
@@ -379,10 +363,12 @@ module ActiveRecord
379
363
  row['name']
380
364
  end
381
365
  end
366
+ alias data_sources tables
382
367
 
383
368
  def table_exists?(table_name)
384
369
  table_name && tables(nil, table_name).any?
385
370
  end
371
+ alias data_source_exists? table_exists?
386
372
 
387
373
  # Returns an array of +Column+ objects for the table specified by +table_name+.
388
374
  def columns(table_name) #:nodoc:
@@ -428,10 +414,9 @@ module ActiveRecord
428
414
  end
429
415
 
430
416
  def primary_key(table_name) #:nodoc:
431
- column = table_structure(table_name).find { |field|
432
- field['pk'] == 1
433
- }
434
- column && column['name']
417
+ pks = table_structure(table_name).select { |f| f['pk'] > 0 }
418
+ return nil unless pks.count == 1
419
+ pks[0]['name']
435
420
  end
436
421
 
437
422
  def remove_index!(table_name, index_name) #:nodoc:
@@ -509,7 +494,6 @@ module ActiveRecord
509
494
  def initialize_type_map(m)
510
495
  super
511
496
  m.register_type(/binary/i, SQLite3Binary.new)
512
- register_class_with_limit m, %r(char)i, SQLite3String
513
497
  end
514
498
 
515
499
  def table_structure(table_name)
@@ -1,6 +1,6 @@
1
1
  module ActiveRecord
2
2
  module ConnectionHandling
3
- RAILS_ENV = -> { (Rails.env if defined?(Rails)) || ENV["RAILS_ENV"] || ENV["RACK_ENV"] }
3
+ RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"] || ENV["RACK_ENV"] }
4
4
  DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
5
5
 
6
6
  # Establishes the connection to the database. Accepts a hash as input where
@@ -114,16 +114,16 @@ module ActiveRecord
114
114
  super
115
115
  end
116
116
 
117
- def initialize_find_by_cache
117
+ def initialize_find_by_cache # :nodoc:
118
118
  self.find_by_statement_cache = {}.extend(Mutex_m)
119
119
  end
120
120
 
121
- def inherited(child_class)
121
+ def inherited(child_class) # :nodoc:
122
122
  child_class.initialize_find_by_cache
123
123
  super
124
124
  end
125
125
 
126
- def find(*ids)
126
+ def find(*ids) # :nodoc:
127
127
  # We don't have cache keys for this stuff yet
128
128
  return super unless ids.length == 1
129
129
  # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
@@ -131,6 +131,7 @@ module ActiveRecord
131
131
  return super if block_given? ||
132
132
  primary_key.nil? ||
133
133
  default_scopes.any? ||
134
+ current_scope ||
134
135
  columns_hash.include?(inheritance_column) ||
135
136
  ids.first.kind_of?(Array)
136
137
 
@@ -158,7 +159,7 @@ module ActiveRecord
158
159
  raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
159
160
  end
160
161
 
161
- def find_by(*args)
162
+ def find_by(*args) # :nodoc:
162
163
  return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
163
164
  return super if default_scopes.any?
164
165
 
@@ -191,11 +192,11 @@ module ActiveRecord
191
192
  end
192
193
  end
193
194
 
194
- def find_by!(*args)
195
+ def find_by!(*args) # :nodoc:
195
196
  find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
196
197
  end
197
198
 
198
- def initialize_generated_modules
199
+ def initialize_generated_modules # :nodoc:
199
200
  generated_association_methods
200
201
  end
201
202
 
@@ -270,11 +271,11 @@ module ActiveRecord
270
271
  # User.new(first_name: 'Jamie')
271
272
  def initialize(attributes = nil, options = {})
272
273
  @attributes = self.class._default_attributes.dup
274
+ self.class.define_attribute_methods
273
275
 
274
276
  init_internals
275
277
  initialize_internals_callback
276
278
 
277
- self.class.define_attribute_methods
278
279
  # +options+ argument is only needed to make protected_attributes gem easier to hook.
279
280
  # Remove it when we drop support to this gem.
280
281
  init_attributes(attributes, options) if attributes
@@ -283,17 +284,22 @@ module ActiveRecord
283
284
  _run_initialize_callbacks
284
285
  end
285
286
 
286
- # Initialize an empty model object from +coder+. +coder+ must contain
287
- # the attributes necessary for initializing an empty model object. For
288
- # example:
287
+ # Initialize an empty model object from +coder+. +coder+ should be
288
+ # the result of previously encoding an Active Record model, using
289
+ # `encode_with`
289
290
  #
290
291
  # class Post < ActiveRecord::Base
291
292
  # end
292
293
  #
294
+ # old_post = Post.new(title: "hello world")
295
+ # coder = {}
296
+ # old_post.encode_with(coder)
297
+ #
293
298
  # post = Post.allocate
294
- # post.init_with('attributes' => { 'title' => 'hello world' })
299
+ # post.init_with(coder)
295
300
  # post.title # => 'hello world'
296
301
  def init_with(coder)
302
+ coder = LegacyYamlAdapter.convert(self.class, coder)
297
303
  @attributes = coder['attributes']
298
304
 
299
305
  init_internals
@@ -367,6 +373,7 @@ module ActiveRecord
367
373
  coder['raw_attributes'] = attributes_before_type_cast
368
374
  coder['attributes'] = @attributes
369
375
  coder['new_record'] = new_record?
376
+ coder['active_record_yaml_version'] = 0
370
377
  end
371
378
 
372
379
  # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
@@ -452,6 +459,7 @@ module ActiveRecord
452
459
  # Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
453
460
  # when pp is required.
454
461
  def pretty_print(pp)
462
+ return super if custom_inspect_method_defined?
455
463
  pp.object_address_group(self) do
456
464
  if defined?(@attributes) && @attributes
457
465
  column_names = self.class.column_names.select { |name| has_attribute?(name) || new_record? }
@@ -477,16 +485,16 @@ module ActiveRecord
477
485
  Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
478
486
  end
479
487
 
488
+ private
489
+
480
490
  def set_transaction_state(state) # :nodoc:
481
491
  @transaction_state = state
482
492
  end
483
493
 
484
494
  def has_transactional_callbacks? # :nodoc:
485
- !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
495
+ !_rollback_callbacks.empty? || !_commit_callbacks.empty?
486
496
  end
487
497
 
488
- private
489
-
490
498
  # Updates the attributes on this particular ActiveRecord object so that
491
499
  # if it is associated with a transaction, then the state of the AR object
492
500
  # will be updated to reflect the current state of the transaction
@@ -509,6 +517,8 @@ module ActiveRecord
509
517
  end
510
518
 
511
519
  def update_attributes_from_transaction_state(transaction_state, depth)
520
+ @reflects_state = [false] if depth == 0
521
+
512
522
  if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
513
523
  unless @reflects_state[depth]
514
524
  restore_transaction_record_state if transaction_state.rolledback?
@@ -545,7 +555,6 @@ module ActiveRecord
545
555
  @txn = nil
546
556
  @_start_transaction_state = {}
547
557
  @transaction_state = nil
548
- @reflects_state = [false]
549
558
  end
550
559
 
551
560
  def initialize_internals_callback
@@ -562,5 +571,9 @@ module ActiveRecord
562
571
  @attributes = @attributes.dup
563
572
  end
564
573
  end
574
+
575
+ def custom_inspect_method_defined?
576
+ self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
577
+ end
565
578
  end
566
579
  end