activerecord 5.1.5 → 5.2.8.1

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +655 -608
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +7 -5
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +41 -37
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +14 -5
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +59 -47
  22. data/lib/active_record/associations/collection_proxy.rb +20 -49
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +12 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +36 -30
  26. data/lib/active_record/associations/has_one_association.rb +12 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  31. data/lib/active_record/associations/join_dependency.rb +48 -93
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  34. data/lib/active_record/associations/preloader.rb +18 -38
  35. data/lib/active_record/associations/singular_association.rb +14 -16
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +40 -63
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +32 -216
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +9 -3
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +35 -19
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +12 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +15 -1
  55. data/lib/active_record/collection_cache_key.rb +12 -8
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +142 -42
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +110 -173
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -112
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +66 -74
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +82 -95
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +51 -61
  129. data/lib/active_record/counter_cache.rb +20 -15
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +18 -13
  133. data/lib/active_record/errors.rb +60 -15
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +30 -42
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +47 -9
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +19 -24
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +198 -49
  156. data/lib/active_record/query_cache.rb +12 -14
  157. data/lib/active_record/querying.rb +4 -2
  158. data/lib/active_record/railtie.rb +80 -6
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +108 -194
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +46 -20
  167. data/lib/active_record/relation/delegation.rb +45 -27
  168. data/lib/active_record/relation/finder_methods.rb +77 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +53 -23
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +60 -79
  179. data/lib/active_record/relation/query_attribute.rb +28 -2
  180. data/lib/active_record/relation/query_methods.rb +129 -100
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +4 -2
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +120 -214
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +8 -9
  193. data/lib/active_record/scoping/named.rb +23 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +23 -13
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +13 -6
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +33 -28
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +6 -0
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +26 -40
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -114
  254. data/lib/active_record/attribute_set/builder.rb +0 -124
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
  require "zlib"
3
5
  require "active_support/core_ext/module/attribute_accessors"
@@ -138,6 +140,7 @@ module ActiveRecord
138
140
 
139
141
  class ConcurrentMigrationError < MigrationError #:nodoc:
140
142
  DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running.".freeze
143
+ RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock".freeze
141
144
 
142
145
  def initialize(message = DEFAULT_MESSAGE)
143
146
  super
@@ -157,7 +160,7 @@ module ActiveRecord
157
160
 
158
161
  class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
159
162
  def initialize(env = "production")
160
- msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
163
+ msg = "You are attempting to run a destructive action against your '#{env}' database.\n".dup
161
164
  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
162
165
  msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
163
166
  super(msg)
@@ -166,7 +169,7 @@ module ActiveRecord
166
169
 
167
170
  class EnvironmentMismatchError < ActiveRecordError
168
171
  def initialize(current: nil, stored: nil)
169
- msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
172
+ msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n".dup
170
173
  msg << "You are running in `#{ current }` environment. "
171
174
  msg << "If you are sure you want to continue, first set the environment using:\n\n"
172
175
  msg << " bin/rails db:environment:set"
@@ -352,9 +355,9 @@ module ActiveRecord
352
355
  # to match the structure of your database.
353
356
  #
354
357
  # To roll the database back to a previous migration version, use
355
- # <tt>rails db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
358
+ # <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
356
359
  # you wish to downgrade. Alternatively, you can also use the STEP option if you
357
- # wish to rollback last few migrations. <tt>rails db:migrate STEP=2</tt> will rollback
360
+ # wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
358
361
  # the latest two migrations.
359
362
  #
360
363
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
@@ -548,7 +551,7 @@ module ActiveRecord
548
551
  end
549
552
 
550
553
  def call(env)
551
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
554
+ mtime = ActiveRecord::Base.connection.migration_context.last_migration.mtime.to_i
552
555
  if @last_check < mtime
553
556
  ActiveRecord::Migration.check_pending!(connection)
554
557
  @last_check = mtime
@@ -573,13 +576,14 @@ module ActiveRecord
573
576
 
574
577
  # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
575
578
  def check_pending!(connection = Base.connection)
576
- raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
579
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
577
580
  end
578
581
 
579
582
  def load_schema_if_pending!
580
- if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
583
+ if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
581
584
  # Roundtrip to Rake to allow plugins to hook into database initialization.
582
- FileUtils.cd Rails.root do
585
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
586
+ FileUtils.cd(root) do
583
587
  current_config = Base.connection_config
584
588
  Base.clear_all_connections!
585
589
  system("bin/rails db:test:prepare")
@@ -731,6 +735,24 @@ module ActiveRecord
731
735
  execute_block { yield helper }
732
736
  end
733
737
 
738
+ # Used to specify an operation that is only run when migrating up
739
+ # (for example, populating a new column with its initial values).
740
+ #
741
+ # In the following example, the new column +published+ will be given
742
+ # the value +true+ for all existing records.
743
+ #
744
+ # class AddPublishedToPosts < ActiveRecord::Migration[5.2]
745
+ # def change
746
+ # add_column :posts, :published, :boolean, default: false
747
+ # up_only do
748
+ # execute "update posts set published = 'true'"
749
+ # end
750
+ # end
751
+ # end
752
+ def up_only
753
+ execute_block { yield } unless reverting?
754
+ end
755
+
734
756
  # Runs the given migration classes.
735
757
  # Last argument can specify options:
736
758
  # - :direction (default is :up)
@@ -855,23 +877,25 @@ module ActiveRecord
855
877
 
856
878
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
857
879
 
858
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
880
+ destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
859
881
  last = destination_migrations.last
860
882
  sources.each do |scope, path|
861
- source_migrations = ActiveRecord::Migrator.migrations(path)
883
+ source_migrations = ActiveRecord::MigrationContext.new(path).migrations
862
884
 
863
885
  source_migrations.each do |migration|
864
886
  source = File.binread(migration.filename)
865
887
  inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
866
- if /\A#.*\b(?:en)?coding:\s*\S+/ =~ source
888
+ magic_comments = "".dup
889
+ loop do
867
890
  # If we have a magic comment in the original migration,
868
891
  # insert our comment after the first newline(end of the magic comment line)
869
892
  # so the magic keep working.
870
893
  # Note that magic comments must be at the first line(except sh-bang).
871
- source[/\n/] = "\n#{inserted_comment}"
872
- else
873
- source = "#{inserted_comment}#{source}"
894
+ source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*\n/) do |magic_comment|
895
+ magic_comments << magic_comment; ""
896
+ end || break
874
897
  end
898
+ source = "#{magic_comments}#{inserted_comment}#{source}"
875
899
 
876
900
  if duplicate = destination_migrations.detect { |m| m.name == migration.name }
877
901
  if options[:on_skip] && duplicate.scope != scope.to_s
@@ -974,146 +998,184 @@ module ActiveRecord
974
998
  end
975
999
  end
976
1000
 
977
- class Migrator#:nodoc:
978
- class << self
979
- attr_writer :migrations_paths
980
- alias :migrations_path= :migrations_paths=
981
-
982
- def migrate(migrations_paths, target_version = nil, &block)
983
- case
984
- when target_version.nil?
985
- up(migrations_paths, target_version, &block)
986
- when current_version == 0 && target_version == 0
987
- []
988
- when current_version > target_version
989
- down(migrations_paths, target_version, &block)
990
- else
991
- up(migrations_paths, target_version, &block)
992
- end
993
- end
1001
+ class MigrationContext # :nodoc:
1002
+ attr_reader :migrations_paths
994
1003
 
995
- def rollback(migrations_paths, steps = 1)
996
- move(:down, migrations_paths, steps)
997
- end
1004
+ def initialize(migrations_paths)
1005
+ @migrations_paths = migrations_paths
1006
+ end
998
1007
 
999
- def forward(migrations_paths, steps = 1)
1000
- move(:up, migrations_paths, steps)
1008
+ def migrate(target_version = nil, &block)
1009
+ case
1010
+ when target_version.nil?
1011
+ up(target_version, &block)
1012
+ when current_version == 0 && target_version == 0
1013
+ []
1014
+ when current_version > target_version
1015
+ down(target_version, &block)
1016
+ else
1017
+ up(target_version, &block)
1001
1018
  end
1019
+ end
1020
+
1021
+ def rollback(steps = 1)
1022
+ move(:down, steps)
1023
+ end
1002
1024
 
1003
- def up(migrations_paths, target_version = nil)
1004
- migrations = migrations(migrations_paths)
1005
- migrations.select! { |m| yield m } if block_given?
1025
+ def forward(steps = 1)
1026
+ move(:up, steps)
1027
+ end
1006
1028
 
1007
- new(:up, migrations, target_version).migrate
1029
+ def up(target_version = nil)
1030
+ selected_migrations = if block_given?
1031
+ migrations.select { |m| yield m }
1032
+ else
1033
+ migrations
1008
1034
  end
1009
1035
 
1010
- def down(migrations_paths, target_version = nil)
1011
- migrations = migrations(migrations_paths)
1012
- migrations.select! { |m| yield m } if block_given?
1036
+ Migrator.new(:up, selected_migrations, target_version).migrate
1037
+ end
1013
1038
 
1014
- new(:down, migrations, target_version).migrate
1039
+ def down(target_version = nil)
1040
+ selected_migrations = if block_given?
1041
+ migrations.select { |m| yield m }
1042
+ else
1043
+ migrations
1015
1044
  end
1016
1045
 
1017
- def run(direction, migrations_paths, target_version)
1018
- new(direction, migrations(migrations_paths), target_version).run
1019
- end
1046
+ Migrator.new(:down, selected_migrations, target_version).migrate
1047
+ end
1020
1048
 
1021
- def open(migrations_paths)
1022
- new(:up, migrations(migrations_paths), nil)
1023
- end
1049
+ def run(direction, target_version)
1050
+ Migrator.new(direction, migrations, target_version).run
1051
+ end
1024
1052
 
1025
- def schema_migrations_table_name
1026
- SchemaMigration.table_name
1027
- end
1028
- deprecate :schema_migrations_table_name
1053
+ def open
1054
+ Migrator.new(:up, migrations, nil)
1055
+ end
1029
1056
 
1030
- def get_all_versions(connection = Base.connection)
1031
- if SchemaMigration.table_exists?
1032
- SchemaMigration.all_versions.map(&:to_i)
1033
- else
1034
- []
1035
- end
1057
+ def get_all_versions
1058
+ if SchemaMigration.table_exists?
1059
+ SchemaMigration.all_versions.map(&:to_i)
1060
+ else
1061
+ []
1036
1062
  end
1063
+ end
1037
1064
 
1038
- def current_version(connection = Base.connection)
1039
- get_all_versions(connection).max || 0
1040
- end
1065
+ def current_version
1066
+ get_all_versions.max || 0
1067
+ rescue ActiveRecord::NoDatabaseError
1068
+ end
1041
1069
 
1042
- def needs_migration?(connection = Base.connection)
1043
- (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
1044
- end
1070
+ def needs_migration?
1071
+ (migrations.collect(&:version) - get_all_versions).size > 0
1072
+ end
1045
1073
 
1046
- def any_migrations?
1047
- migrations(migrations_paths).any?
1048
- end
1074
+ def any_migrations?
1075
+ migrations.any?
1076
+ end
1049
1077
 
1050
- def last_migration #:nodoc:
1051
- migrations(migrations_paths).last || NullMigration.new
1052
- end
1078
+ def last_migration #:nodoc:
1079
+ migrations.last || NullMigration.new
1080
+ end
1053
1081
 
1054
- def migrations_paths
1055
- @migrations_paths ||= ["db/migrate"]
1056
- # just to not break things if someone uses: migrations_path = some_string
1057
- Array(@migrations_paths)
1058
- end
1082
+ def parse_migration_filename(filename) # :nodoc:
1083
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1084
+ end
1059
1085
 
1060
- def parse_migration_filename(filename) # :nodoc:
1061
- File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1086
+ def migrations
1087
+ migrations = migration_files.map do |file|
1088
+ version, name, scope = parse_migration_filename(file)
1089
+ raise IllegalMigrationNameError.new(file) unless version
1090
+ version = version.to_i
1091
+ name = name.camelize
1092
+
1093
+ MigrationProxy.new(name, version, file, scope)
1062
1094
  end
1063
1095
 
1064
- def migrations(paths)
1065
- paths = Array(paths)
1096
+ migrations.sort_by(&:version)
1097
+ end
1066
1098
 
1067
- migrations = migration_files(paths).map do |file|
1068
- version, name, scope = parse_migration_filename(file)
1069
- raise IllegalMigrationNameError.new(file) unless version
1070
- version = version.to_i
1071
- name = name.camelize
1099
+ def migrations_status
1100
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
1072
1101
 
1073
- MigrationProxy.new(name, version, file, scope)
1074
- end
1102
+ file_list = migration_files.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
1075
1109
 
1076
- migrations.sort_by(&:version)
1110
+ db_list.map! do |version|
1111
+ ["up", version, "********** NO FILE **********"]
1077
1112
  end
1078
1113
 
1079
- def migrations_status(paths)
1080
- paths = Array(paths)
1114
+ (db_list + file_list).sort_by { |_, version, _| version }
1115
+ end
1116
+
1117
+ def migration_files
1118
+ paths = Array(migrations_paths)
1119
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1120
+ end
1121
+
1122
+ def current_environment
1123
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1124
+ end
1125
+
1126
+ def protected_environment?
1127
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1128
+ end
1129
+
1130
+ def last_stored_environment
1131
+ return nil if current_version == 0
1132
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1081
1133
 
1082
- db_list = ActiveRecord::SchemaMigration.normalized_versions
1134
+ environment = ActiveRecord::InternalMetadata[:environment]
1135
+ raise NoEnvironmentInSchemaError unless environment
1136
+ environment
1137
+ end
1083
1138
 
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
1139
+ private
1140
+ def move(direction, steps)
1141
+ migrator = Migrator.new(direction, migrations)
1091
1142
 
1092
- db_list.map! do |version|
1093
- ["up", version, "********** NO FILE **********"]
1143
+ if current_version != 0 && !migrator.current_migration
1144
+ raise UnknownMigrationVersionError.new(current_version)
1094
1145
  end
1095
1146
 
1096
- (db_list + file_list).sort_by { |_, version, _| version }
1097
- end
1147
+ start_index =
1148
+ if current_version == 0
1149
+ 0
1150
+ else
1151
+ migrator.migrations.index(migrator.current_migration)
1152
+ end
1098
1153
 
1099
- def migration_files(paths)
1100
- Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1154
+ finish = migrator.migrations[start_index + steps]
1155
+ version = finish ? finish.version : 0
1156
+ send(direction, version)
1101
1157
  end
1158
+ end
1102
1159
 
1103
- private
1160
+ class Migrator # :nodoc:
1161
+ class << self
1162
+ attr_accessor :migrations_paths
1104
1163
 
1105
- def move(direction, migrations_paths, steps)
1106
- migrator = new(direction, migrations(migrations_paths))
1107
- start_index = migrator.migrations.index(migrator.current_migration)
1164
+ def migrations_path=(path)
1165
+ ActiveSupport::Deprecation.warn \
1166
+ "`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
1167
+ "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
1168
+ self.migrations_paths = [path]
1169
+ end
1108
1170
 
1109
- if start_index
1110
- finish = migrator.migrations[start_index + steps]
1111
- version = finish ? finish.version : 0
1112
- send(direction, migrations_paths, version)
1113
- end
1171
+ # For cases where a table doesn't exist like loading from schema cache
1172
+ def current_version
1173
+ MigrationContext.new(migrations_paths).current_version
1114
1174
  end
1115
1175
  end
1116
1176
 
1177
+ self.migrations_paths = ["db/migrate"]
1178
+
1117
1179
  def initialize(direction, migrations, target_version = nil)
1118
1180
  @direction = direction
1119
1181
  @target_version = target_version
@@ -1176,7 +1238,7 @@ module ActiveRecord
1176
1238
  end
1177
1239
 
1178
1240
  def load_migrated
1179
- @migrated_versions = Set.new(self.class.get_all_versions)
1241
+ @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
1180
1242
  end
1181
1243
 
1182
1244
  private
@@ -1208,7 +1270,7 @@ module ActiveRecord
1208
1270
  # Stores the current environment in the database.
1209
1271
  def record_environment
1210
1272
  return if down?
1211
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
1273
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1212
1274
  end
1213
1275
 
1214
1276
  def ran?(migration)
@@ -1217,7 +1279,7 @@ module ActiveRecord
1217
1279
 
1218
1280
  # Return true if a valid version is not provided.
1219
1281
  def invalid_target?
1220
- !target && @target_version && @target_version > 0
1282
+ @target_version && @target_version != 0 && !target
1221
1283
  end
1222
1284
 
1223
1285
  def execute_migration_in_transaction(migration, direction)
@@ -1231,7 +1293,7 @@ module ActiveRecord
1231
1293
  record_version_state_after_migrating(migration.version)
1232
1294
  end
1233
1295
  rescue => e
1234
- msg = "An error has occurred, "
1296
+ msg = "An error has occurred, ".dup
1235
1297
  msg << "this and " if use_transaction?(migration)
1236
1298
  msg << "all later migrations canceled:\n\n#{e}"
1237
1299
  raise StandardError, msg, e.backtrace
@@ -1250,10 +1312,10 @@ module ActiveRecord
1250
1312
  end
1251
1313
 
1252
1314
  def validate(migrations)
1253
- name , = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1315
+ name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
1254
1316
  raise DuplicateMigrationNameError.new(name) if name
1255
1317
 
1256
- version , = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1318
+ version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
1257
1319
  raise DuplicateMigrationVersionError.new(version) if version
1258
1320
  end
1259
1321
 
@@ -1267,23 +1329,6 @@ module ActiveRecord
1267
1329
  end
1268
1330
  end
1269
1331
 
1270
- def self.last_stored_environment
1271
- return nil if current_version == 0
1272
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1273
-
1274
- environment = ActiveRecord::InternalMetadata[:environment]
1275
- raise NoEnvironmentInSchemaError unless environment
1276
- environment
1277
- end
1278
-
1279
- def self.current_environment
1280
- ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
1281
- end
1282
-
1283
- def self.protected_environment?
1284
- ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
1285
- end
1286
-
1287
1332
  def up?
1288
1333
  @direction == :up
1289
1334
  end
@@ -1311,12 +1356,17 @@ module ActiveRecord
1311
1356
 
1312
1357
  def with_advisory_lock
1313
1358
  lock_id = generate_migrator_advisory_lock_id
1314
- got_lock = Base.connection.get_advisory_lock(lock_id)
1359
+ connection = Base.connection
1360
+ got_lock = connection.get_advisory_lock(lock_id)
1315
1361
  raise ConcurrentMigrationError unless got_lock
1316
1362
  load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1317
1363
  yield
1318
1364
  ensure
1319
- Base.connection.release_advisory_lock(lock_id) if got_lock
1365
+ if got_lock && !connection.release_advisory_lock(lock_id)
1366
+ raise ConcurrentMigrationError.new(
1367
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1368
+ )
1369
+ end
1320
1370
  end
1321
1371
 
1322
1372
  MIGRATOR_SALT = 2053462845
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "monitor"
2
4
 
3
5
  module ActiveRecord
@@ -103,20 +105,11 @@ module ActiveRecord
103
105
  included do
104
106
  mattr_accessor :primary_key_prefix_type, instance_writer: false
105
107
 
106
- class_attribute :table_name_prefix, instance_writer: false
107
- self.table_name_prefix = ""
108
-
109
- class_attribute :table_name_suffix, instance_writer: false
110
- self.table_name_suffix = ""
111
-
112
- class_attribute :schema_migrations_table_name, instance_accessor: false
113
- self.schema_migrations_table_name = "schema_migrations"
114
-
115
- class_attribute :internal_metadata_table_name, instance_accessor: false
116
- self.internal_metadata_table_name = "ar_internal_metadata"
117
-
118
- class_attribute :pluralize_table_names, instance_writer: false
119
- self.pluralize_table_names = true
108
+ class_attribute :table_name_prefix, instance_writer: false, default: ""
109
+ class_attribute :table_name_suffix, instance_writer: false, default: ""
110
+ class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
111
+ class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
112
+ class_attribute :pluralize_table_names, instance_writer: false, default: true
120
113
 
121
114
  self.protected_environments = ["production"]
122
115
  self.inheritance_column = "type"
@@ -332,11 +325,11 @@ module ActiveRecord
332
325
  end
333
326
 
334
327
  def attributes_builder # :nodoc:
335
- @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key) do |name|
336
- unless columns_hash.key?(name)
337
- _default_attributes[name].dup
338
- end
328
+ unless defined?(@attributes_builder) && @attributes_builder
329
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
330
+ @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
339
331
  end
332
+ @attributes_builder
340
333
  end
341
334
 
342
335
  def columns_hash # :nodoc:
@@ -355,7 +348,7 @@ module ActiveRecord
355
348
  end
356
349
 
357
350
  def yaml_encoder # :nodoc:
358
- @yaml_encoder ||= AttributeSet::YAMLEncoder.new(attribute_types)
351
+ @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
359
352
  end
360
353
 
361
354
  # Returns the type of the attribute with the given name, after applying
@@ -368,8 +361,9 @@ module ActiveRecord
368
361
  # it).
369
362
  #
370
363
  # +attr_name+ The name of the attribute to retrieve the type for. Must be
371
- # a string
364
+ # a string or a symbol.
372
365
  def type_for_attribute(attr_name, &block)
366
+ attr_name = attr_name.to_s
373
367
  if block
374
368
  attribute_types.fetch(attr_name, &block)
375
369
  else
@@ -381,11 +375,12 @@ module ActiveRecord
381
375
  # default values when instantiating the Active Record object for this table.
382
376
  def column_defaults
383
377
  load_schema
384
- _default_attributes.to_hash
378
+ @column_defaults ||= _default_attributes.deep_dup.to_hash
385
379
  end
386
380
 
387
381
  def _default_attributes # :nodoc:
388
- @default_attributes ||= AttributeSet.new({})
382
+ load_schema
383
+ @default_attributes ||= ActiveModel::AttributeSet.new({})
389
384
  end
390
385
 
391
386
  # Returns an array of column names as strings.
@@ -432,7 +427,7 @@ module ActiveRecord
432
427
  # end
433
428
  def reset_column_information
434
429
  connection.clear_cache!
435
- undefine_attribute_methods
430
+ ([self] + descendants).each(&:undefine_attribute_methods)
436
431
  connection.schema_cache.clear_data_source_cache!(table_name)
437
432
 
438
433
  reload_schema_from_cache
@@ -480,12 +475,12 @@ module ActiveRecord
480
475
  end
481
476
 
482
477
  def reload_schema_from_cache
483
- @arel_engine = nil
484
478
  @arel_table = nil
485
479
  @column_names = nil
486
480
  @attribute_types = nil
487
481
  @content_columns = nil
488
482
  @default_attributes = nil
483
+ @column_defaults = nil
489
484
  @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
490
485
  @attributes_builder = nil
491
486
  @columns = nil
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/except"
4
+ require "active_support/core_ext/module/redefine_method"
2
5
  require "active_support/core_ext/object/try"
3
6
  require "active_support/core_ext/hash/indifferent_access"
4
7
 
@@ -10,8 +13,7 @@ module ActiveRecord
10
13
  extend ActiveSupport::Concern
11
14
 
12
15
  included do
13
- class_attribute :nested_attributes_options, instance_writer: false
14
- self.nested_attributes_options = {}
16
+ class_attribute :nested_attributes_options, instance_writer: false, default: {}
15
17
  end
16
18
 
17
19
  # = Active Record Nested Attributes
@@ -61,6 +63,18 @@ module ActiveRecord
61
63
  # member.update params[:member]
62
64
  # member.avatar.icon # => 'sad'
63
65
  #
66
+ # If you want to update the current avatar without providing the id, you must add <tt>:update_only</tt> option.
67
+ #
68
+ # class Member < ActiveRecord::Base
69
+ # has_one :avatar
70
+ # accepts_nested_attributes_for :avatar, update_only: true
71
+ # end
72
+ #
73
+ # params = { member: { avatar_attributes: { icon: 'sad' } } }
74
+ # member.update params[:member]
75
+ # member.avatar.id # => 2
76
+ # member.avatar.icon # => 'sad'
77
+ #
64
78
  # By default you will only be able to set and update attributes on the
65
79
  # associated model. If you want to destroy the associated model through the
66
80
  # attributes hash, you have to enable it first using the
@@ -354,9 +368,7 @@ module ActiveRecord
354
368
  # associations are just regular associations.
355
369
  def generate_association_writer(association_name, type)
356
370
  generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
357
- if method_defined?(:#{association_name}_attributes=)
358
- remove_method(:#{association_name}_attributes=)
359
- end
371
+ silence_redefinition_of_method :#{association_name}_attributes=
360
372
  def #{association_name}_attributes=(attributes)
361
373
  assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
362
374
  end
@@ -458,7 +470,7 @@ module ActiveRecord
458
470
  end
459
471
 
460
472
  unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
461
- raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
473
+ raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
462
474
  end
463
475
 
464
476
  check_record_limit!(options[:limit], attributes_collection)
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record No Touching
3
5
  module NoTouching
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  module ClassMethods
7
- # Lets you selectively disable calls to `touch` for the
9
+ # Lets you selectively disable calls to +touch+ for the
8
10
  # duration of a block.
9
11
  #
10
12
  # ==== Examples