activerecord 5.0.0 → 5.0.1

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +218 -2
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/aggregations.rb +4 -2
  5. data/lib/active_record/association_relation.rb +4 -1
  6. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
  7. data/lib/active_record/associations/builder/singular_association.rb +10 -1
  8. data/lib/active_record/associations/collection_association.rb +22 -17
  9. data/lib/active_record/associations/collection_proxy.rb +20 -7
  10. data/lib/active_record/associations/has_many_through_association.rb +4 -0
  11. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  12. data/lib/active_record/associations/join_dependency.rb +10 -4
  13. data/lib/active_record/associations/preloader/association.rb +18 -4
  14. data/lib/active_record/associations/preloader/collection_association.rb +0 -1
  15. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  16. data/lib/active_record/associations/singular_association.rb +8 -2
  17. data/lib/active_record/associations.rb +5 -0
  18. data/lib/active_record/attribute.rb +3 -3
  19. data/lib/active_record/attribute_methods/primary_key.rb +14 -1
  20. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  21. data/lib/active_record/attribute_methods.rb +3 -7
  22. data/lib/active_record/attribute_set/builder.rb +29 -7
  23. data/lib/active_record/attribute_set.rb +2 -0
  24. data/lib/active_record/attributes.rb +3 -3
  25. data/lib/active_record/autosave_association.rb +15 -11
  26. data/lib/active_record/base.rb +1 -1
  27. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +40 -32
  28. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  29. data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +4 -4
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -7
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +38 -33
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -5
  34. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +43 -45
  35. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  36. data/lib/active_record/connection_adapters/mysql/database_statements.rb +6 -23
  37. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  38. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -5
  39. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
  40. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -1
  41. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  42. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  43. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -1
  44. data/lib/active_record/connection_adapters/postgresql_adapter.rb +6 -2
  45. data/lib/active_record/core.rb +3 -1
  46. data/lib/active_record/enum.rb +6 -5
  47. data/lib/active_record/gem_version.rb +1 -1
  48. data/lib/active_record/integration.rb +13 -10
  49. data/lib/active_record/migration.rb +6 -5
  50. data/lib/active_record/model_schema.rb +134 -47
  51. data/lib/active_record/no_touching.rb +4 -0
  52. data/lib/active_record/persistence.rb +10 -4
  53. data/lib/active_record/query_cache.rb +13 -15
  54. data/lib/active_record/querying.rb +3 -3
  55. data/lib/active_record/railties/controller_runtime.rb +1 -1
  56. data/lib/active_record/reflection.rb +12 -0
  57. data/lib/active_record/relation/calculations.rb +11 -11
  58. data/lib/active_record/relation/delegation.rb +1 -1
  59. data/lib/active_record/relation/finder_methods.rb +11 -9
  60. data/lib/active_record/relation/query_methods.rb +3 -3
  61. data/lib/active_record/relation.rb +7 -4
  62. data/lib/active_record/result.rb +7 -1
  63. data/lib/active_record/sanitization.rb +11 -1
  64. data/lib/active_record/schema_dumper.rb +10 -17
  65. data/lib/active_record/scoping/named.rb +1 -1
  66. data/lib/active_record/statement_cache.rb +2 -2
  67. data/lib/active_record/table_metadata.rb +4 -3
  68. data/lib/active_record/touch_later.rb +6 -1
  69. data/lib/active_record/type/internal/abstract_json.rb +5 -1
  70. data/lib/active_record/validations/uniqueness.rb +3 -4
  71. data/lib/active_record.rb +1 -1
  72. metadata +8 -7
@@ -61,18 +61,18 @@ module ActiveRecord
61
61
  # Most of the methods in the adapter are useful during migrations. Most
62
62
  # notably, the instance methods provided by SchemaStatements are very useful.
63
63
  class AbstractAdapter
64
- ADAPTER_NAME = 'Abstract'.freeze
64
+ ADAPTER_NAME = "Abstract".freeze
65
+ include ActiveSupport::Callbacks
66
+ define_callbacks :checkout, :checkin
67
+
65
68
  include Quoting, DatabaseStatements, SchemaStatements
66
69
  include DatabaseLimits
67
70
  include QueryCache
68
- include ActiveSupport::Callbacks
69
71
  include ColumnDumper
70
72
  include Savepoints
71
73
 
72
74
  SIMPLE_INT = /\A\d+\z/
73
75
 
74
- define_callbacks :checkout, :checkin
75
-
76
76
  attr_accessor :visitor, :pool
77
77
  attr_reader :schema_cache, :owner, :logger
78
78
  alias :in_use? :owner
@@ -184,7 +184,30 @@ module ActiveRecord
184
184
 
185
185
  # this method must only be called while holding connection pool's mutex
186
186
  def expire
187
- @owner = nil
187
+ if in_use?
188
+ if @owner != Thread.current
189
+ raise ActiveRecordError, "Cannot expire connection, " <<
190
+ "it is owned by a different thread: #{@owner}. " <<
191
+ "Current thread: #{Thread.current}."
192
+ end
193
+
194
+ @owner = nil
195
+ else
196
+ raise ActiveRecordError, 'Cannot expire connection, it is not currently leased.'
197
+ end
198
+ end
199
+
200
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
201
+ def steal! # :nodoc:
202
+ if in_use?
203
+ if @owner != Thread.current
204
+ pool.send :remove_connection_from_thread_cache, self, @owner
205
+
206
+ @owner = Thread.current
207
+ end
208
+ else
209
+ raise ActiveRecordError, 'Cannot steal connection, it is not currently leased.'
210
+ end
188
211
  end
189
212
 
190
213
  def unprepared_statement
@@ -383,11 +383,11 @@ module ActiveRecord
383
383
  mysql_index_type = row[:Index_type].downcase.to_sym
384
384
  index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
385
385
  index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
386
- indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using, row[:Index_comment].presence)
386
+ indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], {}, nil, nil, index_type, index_using, row[:Index_comment].presence)
387
387
  end
388
388
 
389
389
  indexes.last.columns << row[:Column_name]
390
- indexes.last.lengths << row[:Sub_part]
390
+ indexes.last.lengths.merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
391
391
  end
392
392
  end
393
393
 
@@ -409,10 +409,13 @@ module ActiveRecord
409
409
  end
410
410
 
411
411
  def table_comment(table_name) # :nodoc:
412
+ schema, name = extract_schema_qualified_name(table_name)
413
+
412
414
  select_value(<<-SQL.strip_heredoc, 'SCHEMA')
413
415
  SELECT table_comment
414
416
  FROM information_schema.tables
415
- WHERE table_name=#{quote(table_name)}
417
+ WHERE table_schema = #{quote(schema)}
418
+ AND table_name = #{quote(name)}
416
419
  SQL
417
420
  end
418
421
 
@@ -460,7 +463,6 @@ module ActiveRecord
460
463
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
461
464
  # In that case, +options+ and the block will be used by create_table.
462
465
  def drop_table(table_name, options = {})
463
- create_table_info_cache.delete(table_name) if create_table_info_cache.key?(table_name)
464
466
  execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
465
467
  end
466
468
 
@@ -506,7 +508,7 @@ module ActiveRecord
506
508
  end
507
509
 
508
510
  def add_sql_comment!(sql, comment) # :nodoc:
509
- sql << " COMMENT #{quote(comment)}" if comment
511
+ sql << " COMMENT #{quote(comment)}" if comment.present?
510
512
  sql
511
513
  end
512
514
 
@@ -515,19 +517,21 @@ module ActiveRecord
515
517
 
516
518
  schema, name = extract_schema_qualified_name(table_name)
517
519
 
518
- fk_info = select_all <<-SQL.strip_heredoc
519
- SELECT fk.referenced_table_name as 'to_table'
520
- ,fk.referenced_column_name as 'primary_key'
521
- ,fk.column_name as 'column'
522
- ,fk.constraint_name as 'name'
520
+ fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
521
+ SELECT fk.referenced_table_name AS 'to_table',
522
+ fk.referenced_column_name AS 'primary_key',
523
+ fk.column_name AS 'column',
524
+ fk.constraint_name AS 'name',
525
+ rc.update_rule AS 'on_update',
526
+ rc.delete_rule AS 'on_delete'
523
527
  FROM information_schema.key_column_usage fk
524
- WHERE fk.referenced_column_name is not null
528
+ JOIN information_schema.referential_constraints rc
529
+ USING (constraint_schema, constraint_name)
530
+ WHERE fk.referenced_column_name IS NOT NULL
525
531
  AND fk.table_schema = #{quote(schema)}
526
532
  AND fk.table_name = #{quote(name)}
527
533
  SQL
528
534
 
529
- create_table_info = create_table_info(table_name)
530
-
531
535
  fk_info.map do |row|
532
536
  options = {
533
537
  column: row['column'],
@@ -535,14 +539,16 @@ module ActiveRecord
535
539
  primary_key: row['primary_key']
536
540
  }
537
541
 
538
- options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE")
539
- options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE")
542
+ options[:on_update] = extract_foreign_key_action(row['on_update'])
543
+ options[:on_delete] = extract_foreign_key_action(row['on_delete'])
540
544
 
541
545
  ForeignKeyDefinition.new(table_name, row['to_table'], options)
542
546
  end
543
547
  end
544
548
 
545
- def table_options(table_name)
549
+ def table_options(table_name) # :nodoc:
550
+ table_options = {}
551
+
546
552
  create_table_info = create_table_info(table_name)
547
553
 
548
554
  # strip create_definitions and partition_options
@@ -551,10 +557,14 @@ module ActiveRecord
551
557
  # strip AUTO_INCREMENT
552
558
  raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
553
559
 
560
+ table_options[:options] = raw_table_options
561
+
554
562
  # strip COMMENT
555
- raw_table_options.sub!(/ COMMENT='.+'/, '')
563
+ if raw_table_options.sub!(/ COMMENT='.+'/, '')
564
+ table_options[:comment] = table_comment(table_name)
565
+ end
556
566
 
557
- raw_table_options
567
+ table_options
558
568
  end
559
569
 
560
570
  # Maps logical Rails types to MySQL-specific data types.
@@ -682,7 +692,7 @@ module ActiveRecord
682
692
 
683
693
  def register_integer_type(mapping, key, options) # :nodoc:
684
694
  mapping.register_type(key) do |sql_type|
685
- if /\bunsigned\z/ === sql_type
695
+ if /\bunsigned\b/ === sql_type
686
696
  Type::UnsignedInteger.new(options)
687
697
  else
688
698
  Type::Integer.new(options)
@@ -702,29 +712,23 @@ module ActiveRecord
702
712
  MySQL::TypeMetadata.new(super(sql_type), extra: extra, strict: strict_mode?)
703
713
  end
704
714
 
705
- def add_index_length(option_strings, column_names, options = {})
706
- if options.is_a?(Hash) && length = options[:length]
715
+ def add_index_length(quoted_columns, **options)
716
+ if length = options[:length]
707
717
  case length
708
718
  when Hash
709
- column_names.each {|name| option_strings[name] += "(#{length[name]})" if length.has_key?(name) && length[name].present?}
719
+ length = length.symbolize_keys
720
+ quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
710
721
  when Integer
711
- column_names.each {|name| option_strings[name] += "(#{length})"}
722
+ quoted_columns.each { |name, column| column << "(#{length})" }
712
723
  end
713
724
  end
714
725
 
715
- return option_strings
726
+ quoted_columns
716
727
  end
717
728
 
718
- def quoted_columns_for_index(column_names, options = {})
719
- option_strings = Hash[column_names.map {|name| [name, '']}]
720
-
721
- # add index length
722
- option_strings = add_index_length(option_strings, column_names, options)
723
-
724
- # add index sort order
725
- option_strings = add_index_sort_order(option_strings, column_names, options)
726
-
727
- column_names.map {|name| quote_column_name(name) + option_strings[name]}
729
+ def add_options_for_index_columns(quoted_columns, **options)
730
+ quoted_columns = add_index_length(quoted_columns, options)
731
+ super
728
732
  end
729
733
 
730
734
  def translate_exception(exception, message)
@@ -883,21 +887,15 @@ module ActiveRecord
883
887
  end
884
888
  end
885
889
 
886
- def extract_foreign_key_action(structure, name, action) # :nodoc:
887
- if structure =~ /CONSTRAINT #{quote_column_name(name)} FOREIGN KEY .* REFERENCES .* ON #{action} (CASCADE|SET NULL|RESTRICT)/
888
- case $1
889
- when 'CASCADE'; :cascade
890
- when 'SET NULL'; :nullify
891
- end
890
+ def extract_foreign_key_action(specifier) # :nodoc:
891
+ case specifier
892
+ when 'CASCADE'; :cascade
893
+ when 'SET NULL'; :nullify
892
894
  end
893
895
  end
894
896
 
895
- def create_table_info_cache # :nodoc:
896
- @create_table_info_cache ||= {}
897
- end
898
-
899
897
  def create_table_info(table_name) # :nodoc:
900
- create_table_info_cache[table_name] ||= select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
898
+ select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
901
899
  end
902
900
 
903
901
  def create_table_definition(*args) # :nodoc:
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  end
21
21
 
22
22
  def unsigned?
23
- /\bunsigned\z/ === sql_type
23
+ /\A(?:enum|set)\b/ !~ sql_type && /\bunsigned\b/ === sql_type
24
24
  end
25
25
 
26
26
  def case_sensitive?
@@ -13,19 +13,6 @@ module ActiveRecord
13
13
  result
14
14
  end
15
15
 
16
- # Returns a record hash with the column names as keys and column values
17
- # as values.
18
- def select_one(arel, name = nil, binds = [])
19
- arel, binds = binds_from_relation(arel, binds)
20
- @connection.query_options.merge!(as: :hash)
21
- select_result(to_sql(arel, binds), name, binds) do |result|
22
- @connection.next_result while @connection.more_results?
23
- result.first
24
- end
25
- ensure
26
- @connection.query_options.merge!(as: :array)
27
- end
28
-
29
16
  # Returns an array of arrays containing the field values.
30
17
  # Order is the same as that returned by +columns+.
31
18
  def select_rows(sql, name = nil, binds = [])
@@ -37,11 +24,9 @@ module ActiveRecord
37
24
 
38
25
  # Executes the SQL statement in the context of this connection.
39
26
  def execute(sql, name = nil)
40
- if @connection
41
- # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
42
- # made since we established the connection
43
- @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
44
- end
27
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
28
+ # made since we established the connection
29
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
45
30
 
46
31
  super
47
32
  end
@@ -84,11 +69,9 @@ module ActiveRecord
84
69
  end
85
70
 
86
71
  def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
87
- if @connection
88
- # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
89
- # made since we established the connection
90
- @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
91
- end
72
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
73
+ # made since we established the connection
74
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
92
75
 
93
76
  type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
94
77
 
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module MySQL
4
4
  module Quoting # :nodoc:
5
- QUOTED_TRUE, QUOTED_FALSE = '1', '0'
5
+ QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
6
6
 
7
7
  def quote_column_name(name)
8
8
  @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
@@ -90,7 +90,6 @@ module ActiveRecord
90
90
  #++
91
91
 
92
92
  def active?
93
- return false unless @connection
94
93
  @connection.ping
95
94
  end
96
95
 
@@ -105,10 +104,7 @@ module ActiveRecord
105
104
  # Otherwise, this method does nothing.
106
105
  def disconnect!
107
106
  super
108
- unless @connection.nil?
109
- @connection.close
110
- @connection = nil
111
- end
107
+ @connection.close
112
108
  end
113
109
 
114
110
  private
@@ -124,6 +124,8 @@ module ActiveRecord
124
124
  pk = primary_key(table_ref) if table_ref
125
125
  end
126
126
 
127
+ pk = suppress_composite_primary_key(pk)
128
+
127
129
  if pk && use_insert_returning?
128
130
  sql = "#{sql} RETURNING #{quote_column_name(pk)}"
129
131
  end
@@ -164,6 +166,12 @@ module ActiveRecord
164
166
  def exec_rollback_db_transaction
165
167
  execute "ROLLBACK"
166
168
  end
169
+
170
+ private
171
+
172
+ def suppress_composite_primary_key(pk)
173
+ pk unless pk.is_a?(Array)
174
+ end
167
175
  end
168
176
  end
169
177
  end
@@ -33,7 +33,11 @@ module ActiveRecord
33
33
 
34
34
  def serialize(value)
35
35
  if value.is_a?(::Array)
36
- @pg_encoder.encode(type_cast_array(value, :serialize))
36
+ result = @pg_encoder.encode(type_cast_array(value, :serialize))
37
+ if encoding = determine_encoding_of_strings(value)
38
+ result.force_encoding(encoding)
39
+ end
40
+ result
37
41
  else
38
42
  super
39
43
  end
@@ -63,6 +67,13 @@ module ActiveRecord
63
67
  @subtype.public_send(method, value)
64
68
  end
65
69
  end
70
+
71
+ def determine_encoding_of_strings(value)
72
+ case value
73
+ when ::Array then determine_encoding_of_strings(value.first)
74
+ when ::String then value.encoding
75
+ end
76
+ end
66
77
  end
67
78
  end
68
79
  end
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  :bit
8
8
  end
9
9
 
10
- def cast(value)
10
+ def cast_value(value)
11
11
  if ::String === value
12
12
  case value
13
13
  when /^0x/i
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  value # Bit-string notation
17
17
  end
18
18
  else
19
- value
19
+ value.to_s
20
20
  end
21
21
  end
22
22
 
@@ -24,6 +24,8 @@ module ActiveRecord
24
24
  def serialize(value)
25
25
  if value.is_a?(::Hash)
26
26
  value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
27
+ elsif value.respond_to?(:to_unsafe_h)
28
+ serialize(value.to_unsafe_h)
27
29
  else
28
30
  value
29
31
  end
@@ -238,6 +238,12 @@ module ActiveRecord
238
238
  PostgreSQLColumn.new(*args)
239
239
  end
240
240
 
241
+ def table_options(table_name) # :nodoc:
242
+ if comment = table_comment(table_name)
243
+ { comment: comment }
244
+ end
245
+ end
246
+
241
247
  # Returns a comment stored in database for given table
242
248
  def table_comment(table_name) # :nodoc:
243
249
  name = Utils.extract_schema_qualified_name(table_name.to_s)
@@ -579,7 +585,7 @@ module ActiveRecord
579
585
  end
580
586
 
581
587
  def foreign_keys(table_name)
582
- fk_info = select_all <<-SQL.strip_heredoc
588
+ fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
583
589
  SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
584
590
  FROM pg_constraint c
585
591
  JOIN pg_class t1 ON c.conrelid = t1.oid
@@ -764,11 +764,15 @@ module ActiveRecord
764
764
  @case_insensitive_cache[column.sql_type] ||= begin
765
765
  sql = <<-end_sql
766
766
  SELECT exists(
767
+ SELECT * FROM pg_proc
768
+ WHERE proname = 'lower'
769
+ AND proargtypes = ARRAY[#{quote column.sql_type}::regtype]::oidvector
770
+ ) OR exists(
767
771
  SELECT * FROM pg_proc
768
772
  INNER JOIN pg_cast
769
- ON casttarget::text::oidvector = proargtypes
773
+ ON ARRAY[casttarget]::oidvector = proargtypes
770
774
  WHERE proname = 'lower'
771
- AND castsource = '#{column.sql_type}'::regtype::oid
775
+ AND castsource = #{quote column.sql_type}::regtype
772
776
  )
773
777
  end_sql
774
778
  execute_and_clear(sql, "SCHEMA", []) do |result|
@@ -310,8 +310,8 @@ module ActiveRecord
310
310
  # # Instantiates a single new object
311
311
  # User.new(first_name: 'Jamie')
312
312
  def initialize(attributes = nil)
313
- @attributes = self.class._default_attributes.deep_dup
314
313
  self.class.define_attribute_methods
314
+ @attributes = self.class._default_attributes.deep_dup
315
315
 
316
316
  init_internals
317
317
  initialize_internals_callback
@@ -346,6 +346,8 @@ module ActiveRecord
346
346
 
347
347
  self.class.define_attribute_methods
348
348
 
349
+ yield self if block_given?
350
+
349
351
  _run_find_callbacks
350
352
  _run_initialize_callbacks
351
353
 
@@ -159,8 +159,9 @@ module ActiveRecord
159
159
  detect_enum_conflict!(name, name)
160
160
  detect_enum_conflict!(name, "#{name}=")
161
161
 
162
- decorate_attribute_type(name, :enum) do |subtype|
163
- EnumType.new(name, enum_values, subtype)
162
+ attr = attribute_alias?(name) ? attribute_alias(name) : name
163
+ decorate_attribute_type(attr, :enum) do |subtype|
164
+ EnumType.new(attr, enum_values, subtype)
164
165
  end
165
166
 
166
167
  _enum_methods_module.module_eval do
@@ -182,15 +183,15 @@ module ActiveRecord
182
183
 
183
184
  # def active?() status == 0 end
184
185
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
185
- define_method("#{value_method_name}?") { self[name] == value.to_s }
186
+ define_method("#{value_method_name}?") { self[attr] == value.to_s }
186
187
 
187
188
  # def active!() update! status: :active end
188
189
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
189
- define_method("#{value_method_name}!") { update! name => value }
190
+ define_method("#{value_method_name}!") { update!(attr => value) }
190
191
 
191
192
  # scope :active, -> { where status: 0 }
192
193
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
193
- klass.scope value_method_name, -> { where(name => value) }
194
+ klass.scope value_method_name, -> { where(attr => value) }
194
195
  end
195
196
  end
196
197
  defined_enums[name.to_s] = enum_values
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  module VERSION
8
8
  MAJOR = 5
9
9
  MINOR = 0
10
- TINY = 0
10
+ TINY = 1
11
11
  PRE = nil
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -53,18 +53,21 @@ module ActiveRecord
53
53
  #
54
54
  # Person.find(5).cache_key(:updated_at, :last_reviewed_at)
55
55
  def cache_key(*timestamp_names)
56
- case
57
- when new_record?
56
+ if new_record?
58
57
  "#{model_name.cache_key}/new"
59
- when timestamp_names.any?
60
- timestamp = max_updated_column_timestamp(timestamp_names)
61
- timestamp = timestamp.utc.to_s(cache_timestamp_format)
62
- "#{model_name.cache_key}/#{id}-#{timestamp}"
63
- when timestamp = max_updated_column_timestamp
64
- timestamp = timestamp.utc.to_s(cache_timestamp_format)
65
- "#{model_name.cache_key}/#{id}-#{timestamp}"
66
58
  else
67
- "#{model_name.cache_key}/#{id}"
59
+ timestamp = if timestamp_names.any?
60
+ max_updated_column_timestamp(timestamp_names)
61
+ else
62
+ max_updated_column_timestamp
63
+ end
64
+
65
+ if timestamp
66
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
67
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
68
+ else
69
+ "#{model_name.cache_key}/#{id}"
70
+ end
68
71
  end
69
72
  end
70
73
 
@@ -1,5 +1,6 @@
1
+ require "set"
2
+ require "zlib"
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
- require 'set'
3
4
 
4
5
  module ActiveRecord
5
6
  class MigrationError < ActiveRecordError#:nodoc:
@@ -126,9 +127,9 @@ module ActiveRecord
126
127
  class PendingMigrationError < MigrationError#:nodoc:
127
128
  def initialize(message = nil)
128
129
  if !message && defined?(Rails.env)
129
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}")
130
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate RAILS_ENV=#{::Rails.env}")
130
131
  elsif !message
131
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate")
132
+ super("Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate")
132
133
  else
133
134
  super
134
135
  end
@@ -145,7 +146,7 @@ module ActiveRecord
145
146
 
146
147
  class NoEnvironmentInSchemaError < MigrationError #:nodoc:
147
148
  def initialize
148
- msg = "Environment data not found in the schema. To resolve this issue, run: \n\n\tbin/rails db:environment:set"
149
+ msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
149
150
  if defined?(Rails.env)
150
151
  super("#{msg} RAILS_ENV=#{::Rails.env}")
151
152
  else
@@ -168,7 +169,7 @@ module ActiveRecord
168
169
  msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
169
170
  msg << "You are running in `#{ current }` environment. "
170
171
  msg << "If you are sure you want to continue, first set the environment using:\n\n"
171
- msg << "\tbin/rails db:environment:set"
172
+ msg << " bin/rails db:environment:set"
172
173
  if defined?(Rails.env)
173
174
  super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
174
175
  else