activerecord 5.2.0.beta2 → 5.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (80) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +231 -2
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record.rb +1 -1
  6. data/lib/active_record/aggregations.rb +4 -5
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations.rb +18 -12
  9. data/lib/active_record/associations/alias_tracker.rb +2 -10
  10. data/lib/active_record/associations/association.rb +1 -1
  11. data/lib/active_record/associations/belongs_to_association.rb +9 -9
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -6
  13. data/lib/active_record/associations/builder/association.rb +2 -2
  14. data/lib/active_record/associations/builder/belongs_to.rb +7 -3
  15. data/lib/active_record/associations/collection_association.rb +2 -2
  16. data/lib/active_record/associations/collection_proxy.rb +1 -1
  17. data/lib/active_record/associations/has_many_association.rb +1 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +4 -17
  19. data/lib/active_record/associations/has_one_through_association.rb +5 -6
  20. data/lib/active_record/associations/preloader.rb +1 -1
  21. data/lib/active_record/associations/preloader/association.rb +2 -2
  22. data/lib/active_record/associations/through_association.rb +22 -9
  23. data/lib/active_record/attribute_methods.rb +1 -5
  24. data/lib/active_record/attribute_methods/dirty.rb +2 -4
  25. data/lib/active_record/attributes.rb +1 -1
  26. data/lib/active_record/autosave_association.rb +3 -0
  27. data/lib/active_record/callbacks.rb +2 -2
  28. data/lib/active_record/collection_cache_key.rb +5 -6
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -3
  30. data/lib/active_record/connection_adapters/abstract/database_statements.rb +57 -21
  31. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -3
  33. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -15
  34. data/lib/active_record/connection_adapters/abstract_adapter.rb +19 -6
  35. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -64
  36. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -1
  37. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +0 -4
  38. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +21 -6
  39. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  40. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  41. data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -1
  42. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -0
  43. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +13 -4
  44. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +170 -48
  45. data/lib/active_record/connection_adapters/postgresql_adapter.rb +15 -5
  46. data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
  47. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +63 -18
  48. data/lib/active_record/core.rb +12 -3
  49. data/lib/active_record/enum.rb +2 -0
  50. data/lib/active_record/fixtures.rb +28 -37
  51. data/lib/active_record/gem_version.rb +1 -1
  52. data/lib/active_record/inheritance.rb +3 -4
  53. data/lib/active_record/log_subscriber.rb +41 -0
  54. data/lib/active_record/migration.rb +138 -120
  55. data/lib/active_record/migration/compatibility.rb +20 -0
  56. data/lib/active_record/model_schema.rb +19 -16
  57. data/lib/active_record/persistence.rb +8 -11
  58. data/lib/active_record/railtie.rb +7 -2
  59. data/lib/active_record/railties/databases.rake +8 -11
  60. data/lib/active_record/reflection.rb +10 -13
  61. data/lib/active_record/relation.rb +27 -17
  62. data/lib/active_record/relation/calculations.rb +17 -12
  63. data/lib/active_record/relation/finder_methods.rb +30 -37
  64. data/lib/active_record/relation/merger.rb +30 -2
  65. data/lib/active_record/relation/predicate_builder.rb +12 -0
  66. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -1
  67. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
  68. data/lib/active_record/relation/query_methods.rb +14 -24
  69. data/lib/active_record/relation/spawn_methods.rb +1 -1
  70. data/lib/active_record/relation/where_clause.rb +16 -2
  71. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  72. data/lib/active_record/sanitization.rb +130 -128
  73. data/lib/active_record/schema.rb +1 -1
  74. data/lib/active_record/schema_dumper.rb +12 -3
  75. data/lib/active_record/scoping/named.rb +6 -0
  76. data/lib/active_record/store.rb +1 -1
  77. data/lib/active_record/table_metadata.rb +10 -3
  78. data/lib/active_record/tasks/database_tasks.rb +4 -4
  79. data/lib/active_record/type_caster/map.rb +1 -1
  80. metadata +9 -9
@@ -550,7 +550,7 @@ module ActiveRecord
550
550
  end
551
551
 
552
552
  def call(env)
553
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
553
+ mtime = ActiveRecord::Base.connection.migration_context.last_migration.mtime.to_i
554
554
  if @last_check < mtime
555
555
  ActiveRecord::Migration.check_pending!(connection)
556
556
  @last_check = mtime
@@ -575,11 +575,11 @@ module ActiveRecord
575
575
 
576
576
  # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
577
577
  def check_pending!(connection = Base.connection)
578
- raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
578
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
579
579
  end
580
580
 
581
581
  def load_schema_if_pending!
582
- if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
582
+ if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
583
583
  # Roundtrip to Rake to allow plugins to hook into database initialization.
584
584
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
585
585
  FileUtils.cd(root) do
@@ -876,10 +876,10 @@ module ActiveRecord
876
876
 
877
877
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
878
878
 
879
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
879
+ destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
880
880
  last = destination_migrations.last
881
881
  sources.each do |scope, path|
882
- source_migrations = ActiveRecord::Migrator.migrations(path)
882
+ source_migrations = ActiveRecord::MigrationContext.new(path).migrations
883
883
 
884
884
  source_migrations.each do |migration|
885
885
  source = File.binread(migration.filename)
@@ -997,131 +997,147 @@ module ActiveRecord
997
997
  end
998
998
  end
999
999
 
1000
- class Migrator#:nodoc:
1001
- class << self
1002
- attr_writer :migrations_paths
1003
- alias :migrations_path= :migrations_paths=
1004
-
1005
- def migrate(migrations_paths, target_version = nil, &block)
1006
- case
1007
- when target_version.nil?
1008
- up(migrations_paths, target_version, &block)
1009
- when current_version == 0 && target_version == 0
1010
- []
1011
- when current_version > target_version
1012
- down(migrations_paths, target_version, &block)
1013
- else
1014
- up(migrations_paths, target_version, &block)
1015
- end
1016
- end
1000
+ class MigrationContext # :nodoc:
1001
+ attr_reader :migrations_paths
1017
1002
 
1018
- def rollback(migrations_paths, steps = 1)
1019
- move(:down, migrations_paths, steps)
1020
- end
1003
+ def initialize(migrations_paths)
1004
+ @migrations_paths = migrations_paths
1005
+ end
1021
1006
 
1022
- def forward(migrations_paths, steps = 1)
1023
- move(:up, migrations_paths, steps)
1007
+ def migrate(target_version = nil, &block)
1008
+ case
1009
+ when target_version.nil?
1010
+ up(target_version, &block)
1011
+ when current_version == 0 && target_version == 0
1012
+ []
1013
+ when current_version > target_version
1014
+ down(target_version, &block)
1015
+ else
1016
+ up(target_version, &block)
1024
1017
  end
1018
+ end
1025
1019
 
1026
- def up(migrations_paths, target_version = nil)
1027
- migrations = migrations(migrations_paths)
1028
- migrations.select! { |m| yield m } if block_given?
1020
+ def rollback(steps = 1)
1021
+ move(:down, steps)
1022
+ end
1029
1023
 
1030
- new(:up, migrations, target_version).migrate
1024
+ def forward(steps = 1)
1025
+ move(:up, steps)
1026
+ end
1027
+
1028
+ def up(target_version = nil)
1029
+ selected_migrations = if block_given?
1030
+ migrations.select { |m| yield m }
1031
+ else
1032
+ migrations
1031
1033
  end
1032
1034
 
1033
- def down(migrations_paths, target_version = nil)
1034
- migrations = migrations(migrations_paths)
1035
- migrations.select! { |m| yield m } if block_given?
1035
+ Migrator.new(:up, selected_migrations, target_version).migrate
1036
+ end
1036
1037
 
1037
- new(:down, migrations, target_version).migrate
1038
+ def down(target_version = nil)
1039
+ selected_migrations = if block_given?
1040
+ migrations.select { |m| yield m }
1041
+ else
1042
+ migrations
1038
1043
  end
1039
1044
 
1040
- def run(direction, migrations_paths, target_version)
1041
- new(direction, migrations(migrations_paths), target_version).run
1042
- end
1045
+ Migrator.new(:down, selected_migrations, target_version).migrate
1046
+ end
1043
1047
 
1044
- def open(migrations_paths)
1045
- new(:up, migrations(migrations_paths), nil)
1046
- end
1048
+ def run(direction, target_version)
1049
+ Migrator.new(direction, migrations, target_version).run
1050
+ end
1047
1051
 
1048
- def get_all_versions(connection = Base.connection)
1049
- if SchemaMigration.table_exists?
1050
- SchemaMigration.all_versions.map(&:to_i)
1051
- else
1052
- []
1053
- end
1054
- end
1052
+ def open
1053
+ Migrator.new(:up, migrations, nil)
1054
+ end
1055
1055
 
1056
- def current_version(connection = Base.connection)
1057
- get_all_versions(connection).max || 0
1056
+ def get_all_versions
1057
+ if SchemaMigration.table_exists?
1058
+ SchemaMigration.all_versions.map(&:to_i)
1059
+ else
1060
+ []
1058
1061
  end
1062
+ end
1059
1063
 
1060
- def needs_migration?(connection = Base.connection)
1061
- (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
1062
- end
1064
+ def current_version
1065
+ get_all_versions.max || 0
1066
+ rescue ActiveRecord::NoDatabaseError
1067
+ end
1063
1068
 
1064
- def any_migrations?
1065
- migrations(migrations_paths).any?
1066
- end
1069
+ def needs_migration?
1070
+ (migrations.collect(&:version) - get_all_versions).size > 0
1071
+ end
1067
1072
 
1068
- def last_migration #:nodoc:
1069
- migrations(migrations_paths).last || NullMigration.new
1070
- end
1073
+ def any_migrations?
1074
+ migrations.any?
1075
+ end
1071
1076
 
1072
- def migrations_paths
1073
- @migrations_paths ||= ["db/migrate"]
1074
- # just to not break things if someone uses: migrations_path = some_string
1075
- Array(@migrations_paths)
1076
- end
1077
+ def last_migration #:nodoc:
1078
+ migrations.last || NullMigration.new
1079
+ end
1077
1080
 
1078
- def parse_migration_filename(filename) # :nodoc:
1079
- File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1081
+ def parse_migration_filename(filename) # :nodoc:
1082
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1083
+ end
1084
+
1085
+ def migrations
1086
+ migrations = migration_files.map do |file|
1087
+ version, name, scope = parse_migration_filename(file)
1088
+ raise IllegalMigrationNameError.new(file) unless version
1089
+ version = version.to_i
1090
+ name = name.camelize
1091
+
1092
+ MigrationProxy.new(name, version, file, scope)
1080
1093
  end
1081
1094
 
1082
- def migrations(paths)
1083
- paths = Array(paths)
1095
+ migrations.sort_by(&:version)
1096
+ end
1084
1097
 
1085
- migrations = migration_files(paths).map do |file|
1086
- version, name, scope = parse_migration_filename(file)
1087
- raise IllegalMigrationNameError.new(file) unless version
1088
- version = version.to_i
1089
- name = name.camelize
1098
+ def migrations_status
1099
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
1090
1100
 
1091
- MigrationProxy.new(name, version, file, scope)
1092
- end
1101
+ file_list = migration_files.map do |file|
1102
+ version, name, scope = parse_migration_filename(file)
1103
+ raise IllegalMigrationNameError.new(file) unless version
1104
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1105
+ status = db_list.delete(version) ? "up" : "down"
1106
+ [status, version, (name + scope).humanize]
1107
+ end.compact
1093
1108
 
1094
- migrations.sort_by(&:version)
1109
+ db_list.map! do |version|
1110
+ ["up", version, "********** NO FILE **********"]
1095
1111
  end
1096
1112
 
1097
- def migrations_status(paths)
1098
- paths = Array(paths)
1099
-
1100
- db_list = ActiveRecord::SchemaMigration.normalized_versions
1113
+ (db_list + file_list).sort_by { |_, version, _| version }
1114
+ end
1101
1115
 
1102
- file_list = migration_files(paths).map do |file|
1103
- version, name, scope = parse_migration_filename(file)
1104
- raise IllegalMigrationNameError.new(file) unless version
1105
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1106
- status = db_list.delete(version) ? "up" : "down"
1107
- [status, version, (name + scope).humanize]
1108
- end.compact
1116
+ def migration_files
1117
+ paths = Array(migrations_paths)
1118
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1119
+ end
1109
1120
 
1110
- db_list.map! do |version|
1111
- ["up", version, "********** NO FILE **********"]
1112
- end
1121
+ def current_environment
1122
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1123
+ end
1113
1124
 
1114
- (db_list + file_list).sort_by { |_, version, _| version }
1115
- end
1125
+ def protected_environment?
1126
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1127
+ end
1116
1128
 
1117
- def migration_files(paths)
1118
- Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1119
- end
1129
+ def last_stored_environment
1130
+ return nil if current_version == 0
1131
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1120
1132
 
1121
- private
1133
+ environment = ActiveRecord::InternalMetadata[:environment]
1134
+ raise NoEnvironmentInSchemaError unless environment
1135
+ environment
1136
+ end
1122
1137
 
1123
- def move(direction, migrations_paths, steps)
1124
- migrator = new(direction, migrations(migrations_paths))
1138
+ private
1139
+ def move(direction, steps)
1140
+ migrator = Migrator.new(direction, migrations)
1125
1141
 
1126
1142
  if current_version != 0 && !migrator.current_migration
1127
1143
  raise UnknownMigrationVersionError.new(current_version)
@@ -1136,10 +1152,29 @@ module ActiveRecord
1136
1152
 
1137
1153
  finish = migrator.migrations[start_index + steps]
1138
1154
  version = finish ? finish.version : 0
1139
- send(direction, migrations_paths, version)
1155
+ send(direction, version)
1156
+ end
1157
+ end
1158
+
1159
+ class Migrator # :nodoc:
1160
+ class << self
1161
+ attr_accessor :migrations_paths
1162
+
1163
+ def migrations_path=(path)
1164
+ ActiveSupport::Deprecation.warn \
1165
+ "ActiveRecord::Migrator.migrations_paths= is now deprecated and will be removed in Rails 6.0." \
1166
+ "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
1167
+ self.migrations_paths = [path]
1168
+ end
1169
+
1170
+ # For cases where a table doesn't exist like loading from schema cache
1171
+ def current_version
1172
+ MigrationContext.new(migrations_paths).current_version
1140
1173
  end
1141
1174
  end
1142
1175
 
1176
+ self.migrations_paths = ["db/migrate"]
1177
+
1143
1178
  def initialize(direction, migrations, target_version = nil)
1144
1179
  @direction = direction
1145
1180
  @target_version = target_version
@@ -1202,7 +1237,7 @@ module ActiveRecord
1202
1237
  end
1203
1238
 
1204
1239
  def load_migrated
1205
- @migrated_versions = Set.new(self.class.get_all_versions)
1240
+ @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
1206
1241
  end
1207
1242
 
1208
1243
  private
@@ -1234,7 +1269,7 @@ module ActiveRecord
1234
1269
  # Stores the current environment in the database.
1235
1270
  def record_environment
1236
1271
  return if down?
1237
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
1272
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1238
1273
  end
1239
1274
 
1240
1275
  def ran?(migration)
@@ -1276,10 +1311,10 @@ module ActiveRecord
1276
1311
  end
1277
1312
 
1278
1313
  def validate(migrations)
1279
- name , = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1314
+ name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1280
1315
  raise DuplicateMigrationNameError.new(name) if name
1281
1316
 
1282
- version , = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1317
+ version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1283
1318
  raise DuplicateMigrationVersionError.new(version) if version
1284
1319
  end
1285
1320
 
@@ -1293,23 +1328,6 @@ module ActiveRecord
1293
1328
  end
1294
1329
  end
1295
1330
 
1296
- def self.last_stored_environment
1297
- return nil if current_version == 0
1298
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1299
-
1300
- environment = ActiveRecord::InternalMetadata[:environment]
1301
- raise NoEnvironmentInSchemaError unless environment
1302
- environment
1303
- end
1304
-
1305
- def self.current_environment
1306
- ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1307
- end
1308
-
1309
- def self.protected_environment?
1310
- ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1311
- end
1312
-
1313
1331
  def up?
1314
1332
  @direction == :up
1315
1333
  end
@@ -16,6 +16,26 @@ module ActiveRecord
16
16
  V5_2 = Current
17
17
 
18
18
  class V5_1 < V5_2
19
+ def change_column(table_name, column_name, type, options = {})
20
+ if adapter_name == "PostgreSQL"
21
+ clear_cache!
22
+ sql = connection.send(:change_column_sql, table_name, column_name, type, options)
23
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{sql}"
24
+ change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
25
+ change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
26
+ change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
27
+ else
28
+ super
29
+ end
30
+ end
31
+
32
+ def create_table(table_name, options = {})
33
+ if adapter_name == "Mysql2"
34
+ super(table_name, options: "ENGINE=InnoDB", **options)
35
+ else
36
+ super
37
+ end
38
+ end
19
39
  end
20
40
 
21
41
  class V5_0 < V5_1
@@ -86,19 +86,6 @@ module ActiveRecord
86
86
  #
87
87
  # Sets the name of the internal metadata table.
88
88
 
89
- ##
90
- # :singleton-method: protected_environments
91
- # :call-seq: protected_environments
92
- #
93
- # The array of names of environments where destructive actions should be prohibited. By default,
94
- # the value is <tt>["production"]</tt>.
95
-
96
- ##
97
- # :singleton-method: protected_environments=
98
- # :call-seq: protected_environments=(environments)
99
- #
100
- # Sets an array of names of environments where destructive actions should be prohibited.
101
-
102
89
  ##
103
90
  # :singleton-method: pluralize_table_names
104
91
  # :call-seq: pluralize_table_names
@@ -122,9 +109,9 @@ module ActiveRecord
122
109
  class_attribute :table_name_suffix, instance_writer: false, default: ""
123
110
  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
124
111
  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
125
- class_attribute :protected_environments, instance_accessor: false, default: [ "production" ]
126
112
  class_attribute :pluralize_table_names, instance_writer: false, default: true
127
113
 
114
+ self.protected_environments = ["production"]
128
115
  self.inheritance_column = "type"
129
116
  self.ignored_columns = [].freeze
130
117
 
@@ -238,6 +225,21 @@ module ActiveRecord
238
225
  (parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
239
226
  end
240
227
 
228
+ # The array of names of environments where destructive actions should be prohibited. By default,
229
+ # the value is <tt>["production"]</tt>.
230
+ def protected_environments
231
+ if defined?(@protected_environments)
232
+ @protected_environments
233
+ else
234
+ superclass.protected_environments
235
+ end
236
+ end
237
+
238
+ # Sets an array of names of environments where destructive actions should be prohibited.
239
+ def protected_environments=(environments)
240
+ @protected_environments = environments.map(&:to_s)
241
+ end
242
+
241
243
  # Defines the name of the table column which will store the class name on single-table
242
244
  # inheritance situations.
243
245
  #
@@ -359,8 +361,9 @@ module ActiveRecord
359
361
  # it).
360
362
  #
361
363
  # +attr_name+ The name of the attribute to retrieve the type for. Must be
362
- # a string
364
+ # a string or a symbol.
363
365
  def type_for_attribute(attr_name, &block)
366
+ attr_name = attr_name.to_s
364
367
  if block
365
368
  attribute_types.fetch(attr_name, &block)
366
369
  else
@@ -423,7 +426,7 @@ module ActiveRecord
423
426
  # end
424
427
  def reset_column_information
425
428
  connection.clear_cache!
426
- undefine_attribute_methods
429
+ ([self] + descendants).each(&:undefine_attribute_methods)
427
430
  connection.schema_cache.clear_data_source_cache!(table_name)
428
431
 
429
432
  reload_schema_from_cache