activerecord 5.0.0 → 5.0.7.2

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.

Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +431 -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/association.rb +11 -1
  7. data/lib/active_record/associations/association_scope.rb +1 -1
  8. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
  9. data/lib/active_record/associations/builder/singular_association.rb +10 -1
  10. data/lib/active_record/associations/collection_association.rb +56 -48
  11. data/lib/active_record/associations/collection_proxy.rb +38 -20
  12. data/lib/active_record/associations/has_many_association.rb +1 -7
  13. data/lib/active_record/associations/has_many_through_association.rb +2 -4
  14. data/lib/active_record/associations/join_dependency/join_association.rb +6 -11
  15. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  16. data/lib/active_record/associations/join_dependency.rb +10 -4
  17. data/lib/active_record/associations/preloader/association.rb +24 -37
  18. data/lib/active_record/associations/preloader/collection_association.rb +0 -1
  19. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  20. data/lib/active_record/associations/preloader/through_association.rb +10 -4
  21. data/lib/active_record/associations/singular_association.rb +8 -2
  22. data/lib/active_record/associations/through_association.rb +1 -1
  23. data/lib/active_record/associations.rb +38 -17
  24. data/lib/active_record/attribute.rb +3 -3
  25. data/lib/active_record/attribute_methods/primary_key.rb +14 -1
  26. data/lib/active_record/attribute_methods/read.rb +1 -1
  27. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -2
  28. data/lib/active_record/attribute_methods.rb +3 -7
  29. data/lib/active_record/attribute_set/builder.rb +37 -13
  30. data/lib/active_record/attribute_set.rb +2 -0
  31. data/lib/active_record/attributes.rb +3 -3
  32. data/lib/active_record/autosave_association.rb +15 -11
  33. data/lib/active_record/base.rb +1 -1
  34. data/lib/active_record/collection_cache_key.rb +16 -6
  35. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +41 -33
  36. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  37. data/lib/active_record/connection_adapters/abstract/query_cache.rb +37 -2
  38. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -5
  39. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +11 -14
  40. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +68 -56
  41. data/lib/active_record/connection_adapters/abstract_adapter.rb +36 -12
  42. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -60
  43. data/lib/active_record/connection_adapters/column.rb +1 -1
  44. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  45. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -25
  46. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  47. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -6
  48. data/lib/active_record/connection_adapters/postgresql/column.rb +28 -1
  49. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
  50. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -2
  51. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  52. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  53. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +10 -0
  54. data/lib/active_record/connection_adapters/postgresql/quoting.rb +32 -3
  55. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -8
  56. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
  57. data/lib/active_record/connection_adapters/postgresql_adapter.rb +25 -19
  58. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  59. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +4 -4
  60. data/lib/active_record/core.rb +6 -4
  61. data/lib/active_record/enum.rb +8 -5
  62. data/lib/active_record/explain.rb +20 -9
  63. data/lib/active_record/fixtures.rb +5 -5
  64. data/lib/active_record/gem_version.rb +2 -2
  65. data/lib/active_record/integration.rb +13 -10
  66. data/lib/active_record/log_subscriber.rb +19 -17
  67. data/lib/active_record/migration.rb +35 -14
  68. data/lib/active_record/model_schema.rb +161 -52
  69. data/lib/active_record/no_touching.rb +4 -0
  70. data/lib/active_record/persistence.rb +41 -20
  71. data/lib/active_record/query_cache.rb +15 -17
  72. data/lib/active_record/querying.rb +3 -3
  73. data/lib/active_record/railties/controller_runtime.rb +1 -1
  74. data/lib/active_record/railties/databases.rake +9 -21
  75. data/lib/active_record/reflection.rb +20 -0
  76. data/lib/active_record/relation/batches.rb +10 -10
  77. data/lib/active_record/relation/calculations.rb +16 -12
  78. data/lib/active_record/relation/delegation.rb +2 -1
  79. data/lib/active_record/relation/finder_methods.rb +13 -11
  80. data/lib/active_record/relation/query_methods.rb +3 -3
  81. data/lib/active_record/relation.rb +12 -5
  82. data/lib/active_record/result.rb +7 -1
  83. data/lib/active_record/sanitization.rb +11 -1
  84. data/lib/active_record/schema_dumper.rb +10 -17
  85. data/lib/active_record/scoping/default.rb +5 -1
  86. data/lib/active_record/scoping/named.rb +18 -6
  87. data/lib/active_record/scoping.rb +4 -3
  88. data/lib/active_record/serialization.rb +1 -1
  89. data/lib/active_record/statement_cache.rb +2 -2
  90. data/lib/active_record/table_metadata.rb +4 -3
  91. data/lib/active_record/tasks/database_tasks.rb +14 -11
  92. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  93. data/lib/active_record/touch_later.rb +6 -1
  94. data/lib/active_record/transactions.rb +1 -1
  95. data/lib/active_record/type/internal/abstract_json.rb +5 -1
  96. data/lib/active_record/validations/uniqueness.rb +3 -4
  97. data/lib/active_record.rb +3 -2
  98. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  99. data/lib/rails/generators/active_record/migration.rb +8 -0
  100. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  101. metadata +7 -8
@@ -230,7 +230,7 @@ module ActiveRecord
230
230
  type_metadata = fetch_type_metadata(column_name, type, oid, fmod)
231
231
  default_value = extract_value_from_default(default)
232
232
  default_function = extract_default_function(default_value, default)
233
- new_column(column_name, default_value, type_metadata, !notnull, table_name, default_function, collation, comment: comment.presence)
233
+ new_column(column_name, default_value, type_metadata, !notnull, table_name, default_function, collation, comment: comment.presence, max_identifier_length: max_identifier_length)
234
234
  end
235
235
  end
236
236
 
@@ -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)
@@ -369,9 +375,17 @@ module ActiveRecord
369
375
 
370
376
  if pk && sequence
371
377
  quoted_sequence = quote_table_name(sequence)
378
+ max_pk = select_value("select MAX(#{quote_column_name pk}) from #{quote_table_name(table)}")
379
+ if max_pk.nil?
380
+ if postgresql_version >= 100000
381
+ minvalue = select_value("SELECT seqmin from pg_sequence where seqrelid = '#{quoted_sequence}'::regclass")
382
+ else
383
+ minvalue = select_value("SELECT min_value FROM #{quoted_sequence}")
384
+ end
385
+ end
372
386
 
373
- select_value(<<-end_sql, 'SCHEMA')
374
- SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
387
+ select_value(<<-end_sql, "SCHEMA")
388
+ SELECT setval('#{quoted_sequence}', #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})
375
389
  end_sql
376
390
  end
377
391
  end
@@ -579,7 +593,7 @@ module ActiveRecord
579
593
  end
580
594
 
581
595
  def foreign_keys(table_name)
582
- fk_info = select_all <<-SQL.strip_heredoc
596
+ fk_info = select_all(<<-SQL.strip_heredoc, 'SCHEMA')
583
597
  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
598
  FROM pg_constraint c
585
599
  JOIN pg_class t1 ON c.conrelid = t1.oid
@@ -615,10 +629,6 @@ module ActiveRecord
615
629
  end
616
630
  end
617
631
 
618
- def index_name_length
619
- 63
620
- end
621
-
622
632
  # Maps logical Rails types to PostgreSQL-specific data types.
623
633
  def type_to_sql(type, limit = nil, precision = nil, scale = nil, array = nil)
624
634
  sql = case type.to_s
@@ -19,9 +19,9 @@ module ActiveRecord
19
19
 
20
20
  def quoted
21
21
  if schema
22
- PGconn.quote_ident(schema) << SEPARATOR << PGconn.quote_ident(identifier)
22
+ PG::Connection.quote_ident(schema) << SEPARATOR << PG::Connection.quote_ident(identifier)
23
23
  else
24
- PGconn.quote_ident(identifier)
24
+ PG::Connection.quote_ident(identifier)
25
25
  end
26
26
  end
27
27
 
@@ -1,5 +1,5 @@
1
1
  # Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
2
- gem 'pg', '~> 0.18'
2
+ gem "pg", ">= 0.18", "< 2.0"
3
3
  require 'pg'
4
4
 
5
5
  require "active_record/connection_adapters/abstract_adapter"
@@ -28,11 +28,11 @@ module ActiveRecord
28
28
  conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
29
29
  conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
30
30
 
31
- # Forward only valid config params to PGconn.connect.
32
- valid_conn_param_keys = PGconn.conndefaults_hash.keys + [:requiressl]
31
+ # Forward only valid config params to PG::Connection.connect.
32
+ valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
33
33
  conn_params.slice!(*valid_conn_param_keys)
34
34
 
35
- # The postgres drivers don't allow the creation of an unconnected PGconn object,
35
+ # The postgres drivers don't allow the creation of an unconnected PG::Connection object,
36
36
  # so just pass a nil connection object for the time being.
37
37
  ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config)
38
38
  end
@@ -198,8 +198,8 @@ module ActiveRecord
198
198
  end
199
199
 
200
200
  def connection_active?
201
- @connection.status == PGconn::CONNECTION_OK
202
- rescue PGError
201
+ @connection.status == PG::CONNECTION_OK
202
+ rescue PG::Error
203
203
  false
204
204
  end
205
205
  end
@@ -212,7 +212,7 @@ module ActiveRecord
212
212
 
213
213
  # @local_tz is initialized as nil to avoid warnings when connect tries to use it
214
214
  @local_tz = nil
215
- @table_alias_length = nil
215
+ @max_identifier_length = nil
216
216
 
217
217
  connect
218
218
  add_pg_encoders
@@ -244,7 +244,7 @@ module ActiveRecord
244
244
  def active?
245
245
  @connection.query 'SELECT 1'
246
246
  true
247
- rescue PGError
247
+ rescue PG::Error
248
248
  false
249
249
  end
250
250
 
@@ -358,9 +358,11 @@ module ActiveRecord
358
358
  end
359
359
 
360
360
  # Returns the configured supported identifier length supported by PostgreSQL
361
- def table_alias_length
362
- @table_alias_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i
361
+ def max_identifier_length
362
+ @max_identifier_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i
363
363
  end
364
+ alias table_alias_length max_identifier_length
365
+ alias index_name_length max_identifier_length
364
366
 
365
367
  # Set the authorized user for this session
366
368
  def session_auth=(user)
@@ -410,7 +412,7 @@ module ActiveRecord
410
412
  def translate_exception(exception, message)
411
413
  return exception unless exception.respond_to?(:result)
412
414
 
413
- case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
415
+ case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
414
416
  when UNIQUE_VIOLATION
415
417
  RecordNotUnique.new(message)
416
418
  when FOREIGN_KEY_VIOLATION
@@ -594,15 +596,15 @@ module ActiveRecord
594
596
  end
595
597
 
596
598
  def exec_no_cache(sql, name, binds)
597
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
598
- log(sql, name, binds) { @connection.async_exec(sql, type_casted_binds) }
599
+ type_casted_binds = type_casted_binds(binds)
600
+ log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) }
599
601
  end
600
602
 
601
603
  def exec_cache(sql, name, binds)
602
604
  stmt_key = prepare_statement(sql)
603
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
605
+ type_casted_binds = type_casted_binds(binds)
604
606
 
605
- log(sql, name, binds, stmt_key) do
607
+ log(sql, name, binds, type_casted_binds, stmt_key) do
606
608
  @connection.exec_prepared(stmt_key, type_casted_binds)
607
609
  end
608
610
  rescue ActiveRecord::StatementInvalid => e
@@ -631,7 +633,7 @@ module ActiveRecord
631
633
  CACHED_PLAN_HEURISTIC = 'cached plan must not change result type'.freeze
632
634
  def is_cached_plan_failure?(e)
633
635
  pgerror = e.cause
634
- code = pgerror.result.result_error_field(PGresult::PG_DIAG_SQLSTATE)
636
+ code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE)
635
637
  code == FEATURE_NOT_SUPPORTED && pgerror.message.include?(CACHED_PLAN_HEURISTIC)
636
638
  rescue
637
639
  false
@@ -668,7 +670,7 @@ module ActiveRecord
668
670
  # Connects to a PostgreSQL server and sets up the adapter depending on the
669
671
  # connected server's characteristics.
670
672
  def connect
671
- @connection = PGconn.connect(@connection_parameters)
673
+ @connection = PG.connect(@connection_parameters)
672
674
  configure_connection
673
675
  rescue ::PG::Error => error
674
676
  if error.message.include?("does not exist")
@@ -764,11 +766,15 @@ module ActiveRecord
764
766
  @case_insensitive_cache[column.sql_type] ||= begin
765
767
  sql = <<-end_sql
766
768
  SELECT exists(
769
+ SELECT * FROM pg_proc
770
+ WHERE proname = 'lower'
771
+ AND proargtypes = ARRAY[#{quote column.sql_type}::regtype]::oidvector
772
+ ) OR exists(
767
773
  SELECT * FROM pg_proc
768
774
  INNER JOIN pg_cast
769
- ON casttarget::text::oidvector = proargtypes
775
+ ON ARRAY[casttarget]::oidvector = proargtypes
770
776
  WHERE proname = 'lower'
771
- AND castsource = '#{column.sql_type}'::regtype::oid
777
+ AND castsource = #{quote column.sql_type}::regtype
772
778
  )
773
779
  end_sql
774
780
  execute_and_clear(sql, "SCHEMA", []) do |result|
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  end
16
16
 
17
17
  def quoted_time(value)
18
- quoted_date(value)
18
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
19
19
  end
20
20
 
21
21
  private
@@ -188,9 +188,9 @@ module ActiveRecord
188
188
  end
189
189
 
190
190
  def exec_query(sql, name = nil, binds = [], prepare: false)
191
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
191
+ type_casted_binds = type_casted_binds(binds)
192
192
 
193
- log(sql, name, binds) do
193
+ log(sql, name, binds, type_casted_binds) do
194
194
  # Don't cache statements if they are not prepared
195
195
  unless prepare
196
196
  stmt = @connection.prepare(sql)
@@ -203,7 +203,6 @@ module ActiveRecord
203
203
  ensure
204
204
  stmt.close
205
205
  end
206
- stmt = records
207
206
  else
208
207
  cache = @statements[sql] ||= {
209
208
  :stmt => @connection.prepare(sql)
@@ -212,9 +211,10 @@ module ActiveRecord
212
211
  cols = cache[:cols] ||= stmt.columns
213
212
  stmt.reset!
214
213
  stmt.bind_params(type_casted_binds)
214
+ records = stmt.to_a
215
215
  end
216
216
 
217
- ActiveRecord::Result.new(cols, stmt.to_a)
217
+ ActiveRecord::Result.new(cols, records)
218
218
  end
219
219
  end
220
220
 
@@ -180,12 +180,12 @@ module ActiveRecord
180
180
  end
181
181
 
182
182
  def find_by(*args) # :nodoc:
183
- return super if scope_attributes? || !(Hash === args.first) || reflect_on_all_aggregations.any?
183
+ return super if scope_attributes? || reflect_on_all_aggregations.any?
184
184
 
185
185
  hash = args.first
186
186
 
187
- return super if hash.values.any? { |v|
188
- v.nil? || Array === v || Hash === v || Relation === v
187
+ return super if !(Hash === hash) || hash.values.any? { |v|
188
+ v.nil? || Array === v || Hash === v || Relation === v || Base === v
189
189
  }
190
190
 
191
191
  # We can't cache Post.find_by(author: david) ...yet
@@ -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
 
@@ -105,6 +105,8 @@ module ActiveRecord
105
105
  end
106
106
 
107
107
  class EnumType < Type::Value # :nodoc:
108
+ delegate :type, to: :subtype
109
+
108
110
  def initialize(name, mapping, subtype)
109
111
  @name = name
110
112
  @mapping = mapping
@@ -159,8 +161,9 @@ module ActiveRecord
159
161
  detect_enum_conflict!(name, name)
160
162
  detect_enum_conflict!(name, "#{name}=")
161
163
 
162
- decorate_attribute_type(name, :enum) do |subtype|
163
- EnumType.new(name, enum_values, subtype)
164
+ attr = attribute_alias?(name) ? attribute_alias(name) : name
165
+ decorate_attribute_type(attr, :enum) do |subtype|
166
+ EnumType.new(attr, enum_values, subtype)
164
167
  end
165
168
 
166
169
  _enum_methods_module.module_eval do
@@ -182,15 +185,15 @@ module ActiveRecord
182
185
 
183
186
  # def active?() status == 0 end
184
187
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
185
- define_method("#{value_method_name}?") { self[name] == value.to_s }
188
+ define_method("#{value_method_name}?") { self[attr] == value.to_s }
186
189
 
187
190
  # def active!() update! status: :active end
188
191
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
189
- define_method("#{value_method_name}!") { update! name => value }
192
+ define_method("#{value_method_name}!") { update!(attr => value) }
190
193
 
191
194
  # scope :active, -> { where status: 0 }
192
195
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
193
- klass.scope value_method_name, -> { where(name => value) }
196
+ klass.scope value_method_name, -> { where(attr => value) }
194
197
  end
195
198
  end
196
199
  defined_enums[name.to_s] = enum_values
@@ -16,15 +16,14 @@ module ActiveRecord
16
16
  # Makes the adapter execute EXPLAIN for the tuples of queries and bindings.
17
17
  # Returns a formatted string ready to be logged.
18
18
  def exec_explain(queries) # :nodoc:
19
- str = queries.map do |sql, bind|
20
- [].tap do |msg|
21
- msg << "EXPLAIN for: #{sql}"
22
- unless bind.empty?
23
- bind_msg = bind.map {|col, val| [col.name, val]}.inspect
24
- msg.last << " #{bind_msg}"
25
- end
26
- msg << connection.explain(sql, bind)
27
- end.join("\n")
19
+ str = queries.map do |sql, binds|
20
+ msg = "EXPLAIN for: #{sql}"
21
+ unless binds.empty?
22
+ msg << " "
23
+ msg << binds.map { |attr| render_bind(attr) }.inspect
24
+ end
25
+ msg << "\n"
26
+ msg << connection.explain(sql, binds)
28
27
  end.join("\n")
29
28
 
30
29
  # Overriding inspect to be more human readable, especially in the console.
@@ -34,5 +33,17 @@ module ActiveRecord
34
33
 
35
34
  str
36
35
  end
36
+
37
+ private
38
+
39
+ def render_bind(attr)
40
+ value = if attr.type.binary? && attr.value
41
+ "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
42
+ else
43
+ connection.type_cast(attr.value_for_database)
44
+ end
45
+
46
+ [attr.name, value]
47
+ end
37
48
  end
38
49
  end
@@ -535,17 +535,17 @@ module ActiveRecord
535
535
 
536
536
  update_all_loaded_fixtures fixtures_map
537
537
 
538
- connection.transaction(:requires_new => true) do
539
- deleted_tables = Set.new
538
+ connection.transaction(requires_new: true) do
539
+ deleted_tables = Hash.new { |h, k| h[k] = Set.new }
540
540
  fixture_sets.each do |fs|
541
541
  conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
542
542
  table_rows = fs.table_rows
543
543
 
544
544
  table_rows.each_key do |table|
545
- unless deleted_tables.include? table
546
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
545
+ unless deleted_tables[conn].include? table
546
+ conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
547
547
  end
548
- deleted_tables << table
548
+ deleted_tables[conn] << table
549
549
  end
550
550
 
551
551
  table_rows.each do |fixture_set_name, rows|
@@ -7,8 +7,8 @@ module ActiveRecord
7
7
  module VERSION
8
8
  MAJOR = 5
9
9
  MINOR = 0
10
- TINY = 0
11
- PRE = nil
10
+ TINY = 7
11
+ PRE = "2"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -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
 
@@ -20,24 +20,9 @@ module ActiveRecord
20
20
  @odd = false
21
21
  end
22
22
 
23
- def render_bind(attribute)
24
- value = if attribute.type.binary? && attribute.value
25
- if attribute.value.is_a?(Hash)
26
- "<#{attribute.value_for_database.to_s.bytesize} bytes of binary data>"
27
- else
28
- "<#{attribute.value.bytesize} bytes of binary data>"
29
- end
30
- else
31
- attribute.value_for_database
32
- end
33
-
34
- [attribute.name, value]
35
- end
36
-
37
23
  def sql(event)
38
- return unless logger.debug?
39
-
40
24
  self.class.runtime += event.duration
25
+ return unless logger.debug?
41
26
 
42
27
  payload = event.payload
43
28
 
@@ -48,7 +33,10 @@ module ActiveRecord
48
33
  binds = nil
49
34
 
50
35
  unless (payload[:binds] || []).empty?
51
- binds = " " + payload[:binds].map { |attr| render_bind(attr) }.inspect
36
+ casted_params = type_casted_binds(payload[:type_casted_binds])
37
+ binds = " " + payload[:binds].zip(casted_params).map { |attr, value|
38
+ render_bind(attr, value)
39
+ }.inspect
52
40
  end
53
41
 
54
42
  name = colorize_payload_name(name, payload[:name])
@@ -59,6 +47,20 @@ module ActiveRecord
59
47
 
60
48
  private
61
49
 
50
+ def type_casted_binds(casted_binds)
51
+ casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
52
+ end
53
+
54
+ def render_bind(attr, value)
55
+ if attr.is_a?(Array)
56
+ attr = attr.first
57
+ elsif attr.type.binary? && attr.value
58
+ value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
59
+ end
60
+
61
+ [attr && attr.name, value]
62
+ end
63
+
62
64
  def colorize_payload_name(name, payload_name)
63
65
  if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
64
66
  color(name, MAGENTA, true)
@@ -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
@@ -1056,10 +1057,6 @@ module ActiveRecord
1056
1057
  Array(@migrations_paths)
1057
1058
  end
1058
1059
 
1059
- def match_to_migration_filename?(filename) # :nodoc:
1060
- File.basename(filename) =~ Migration::MigrationFilenameRegexp
1061
- end
1062
-
1063
1060
  def parse_migration_filename(filename) # :nodoc:
1064
1061
  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1065
1062
  end
@@ -1067,9 +1064,7 @@ module ActiveRecord
1067
1064
  def migrations(paths)
1068
1065
  paths = Array(paths)
1069
1066
 
1070
- files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
1071
-
1072
- migrations = files.map do |file|
1067
+ migrations = migration_files(paths).map do |file|
1073
1068
  version, name, scope = parse_migration_filename(file)
1074
1069
  raise IllegalMigrationNameError.new(file) unless version
1075
1070
  version = version.to_i
@@ -1081,6 +1076,30 @@ module ActiveRecord
1081
1076
  migrations.sort_by(&:version)
1082
1077
  end
1083
1078
 
1079
+ def migrations_status(paths)
1080
+ paths = Array(paths)
1081
+
1082
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
1083
+
1084
+ file_list = migration_files(paths).map do |file|
1085
+ version, name, scope = parse_migration_filename(file)
1086
+ raise IllegalMigrationNameError.new(file) unless version
1087
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1088
+ status = db_list.delete(version) ? "up" : "down"
1089
+ [status, version, (name + scope).humanize]
1090
+ end.compact
1091
+
1092
+ db_list.map! do |version|
1093
+ ["up", version, "********** NO FILE **********"]
1094
+ end
1095
+
1096
+ (db_list + file_list).sort_by { |_, version, _| version }
1097
+ end
1098
+
1099
+ def migration_files(paths)
1100
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1101
+ end
1102
+
1084
1103
  private
1085
1104
 
1086
1105
  def move(direction, migrations_paths, steps)
@@ -1168,9 +1187,10 @@ module ActiveRecord
1168
1187
  def run_without_lock
1169
1188
  migration = migrations.detect { |m| m.version == @target_version }
1170
1189
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1171
- execute_migration_in_transaction(migration, @direction)
1190
+ result = execute_migration_in_transaction(migration, @direction)
1172
1191
 
1173
1192
  record_environment
1193
+ result
1174
1194
  end
1175
1195
 
1176
1196
  # Used for running multiple migrations up to or down to a certain value.
@@ -1179,11 +1199,12 @@ module ActiveRecord
1179
1199
  raise UnknownMigrationVersionError.new(@target_version)
1180
1200
  end
1181
1201
 
1182
- runnable.each do |migration|
1202
+ result = runnable.each do |migration|
1183
1203
  execute_migration_in_transaction(migration, @direction)
1184
1204
  end
1185
1205
 
1186
1206
  record_environment
1207
+ result
1187
1208
  end
1188
1209
 
1189
1210
  # Stores the current environment in the database.