aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md15
-rw-r--r--activerecord/lib/active_record/migration.rb2
-rw-r--r--activerecord/lib/active_record/railties/databases.rake7
-rw-r--r--activerecord/lib/active_record/relation.rb9
-rw-r--r--activerecord/lib/active_record/schema_migration.rb4
-rw-r--r--activerecord/test/cases/ar_schema_test.rb7
-rw-r--r--activerecord/test/cases/persistence_test.rb9
-rw-r--r--guides/source/active_record_querying.md19
8 files changed, 64 insertions, 8 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 6491f32f8f..f09b27d01f 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,18 @@
+* `rake db:migrate:status` works with legacy migration numbers like `00018_xyz.rb`.
+
+ Fixes #15538.
+
+ *Yves Senn*
+
+* Baseclass becomes! subclass.
+
+ Before this change, a record which changed its STI type, could not be
+ updated.
+
+ Fixes #14785.
+
+ *Matthew Draper*, *Earl St Sauver*, *Edo Balvers*
+
* Remove deprecated `ActiveRecord::Migrator.proper_table_name`. Use the
`proper_table_name` instance method on `ActiveRecord::Migration` instead.
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index fca002873c..481e5c17e4 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -711,7 +711,7 @@ module ActiveRecord
if ActiveRecord::Base.timestamped_migrations
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
else
- "%.3d" % number
+ SchemaMigration.normalize_migration_number(number)
end
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index fa25ceaefa..6dca206f2a 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -86,14 +86,15 @@ db_namespace = namespace :db do
abort 'Schema migrations table does not exist yet.'
end
db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
- db_list.map! { |version| "%.3d" % version }
+ db_list.map! { |version| ActiveRecord::SchemaMigration.normalize_migration_number(version) }
file_list = []
ActiveRecord::Migrator.migrations_paths.each do |path|
Dir.foreach(path) do |file|
# match "20091231235959_some_name.rb" and "001_some_name.rb" pattern
if match_data = /^(\d{3,})_(.+)\.rb$/.match(file)
- status = db_list.delete(match_data[1]) ? 'up' : 'down'
- file_list << [status, match_data[1], match_data[2].humanize]
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(match_data[1])
+ status = db_list.delete(version) ? 'up' : 'down'
+ file_list << [status, version, match_data[2].humanize]
end
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index d92ff781ee..cef40be7ce 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -74,7 +74,14 @@ module ActiveRecord
def _update_record(values, id, id_was) # :nodoc:
substitutes, binds = substitute_values values
- um = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id)).arel.compile_update(substitutes, @klass.primary_key)
+
+ scope = @klass.unscoped
+
+ if @klass.finder_needs_type_condition?
+ scope.unscope!(where: @klass.inheritance_column)
+ end
+
+ um = scope.where(@klass.arel_table[@klass.primary_key].eq(id_was || id)).arel.compile_update(substitutes, @klass.primary_key)
@klass.connection.update(
um,
diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb
index a9d164e366..5e484ded75 100644
--- a/activerecord/lib/active_record/schema_migration.rb
+++ b/activerecord/lib/active_record/schema_migration.rb
@@ -36,6 +36,10 @@ module ActiveRecord
connection.drop_table(table_name)
end
end
+
+ def normalize_migration_number(number)
+ "%.3d" % number.to_i
+ end
end
def version
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index 811695938e..861b8cbaa7 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -66,5 +66,12 @@ if ActiveRecord::Base.connection.supports_migrations?
end
assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
end
+
+ def test_normalize_version
+ assert_equal "118", ActiveRecord::SchemaMigration.normalize_migration_number("0000118")
+ assert_equal "002", ActiveRecord::SchemaMigration.normalize_migration_number("2")
+ assert_equal "017", ActiveRecord::SchemaMigration.normalize_migration_number("0017")
+ assert_equal "20131219224947", ActiveRecord::SchemaMigration.normalize_migration_number("20131219224947")
+ end
end
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index bc5ccd0fe9..16f481c289 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -333,6 +333,15 @@ class PersistenceTest < ActiveRecord::TestCase
assert_equal "Reply", topic.type
end
+ def test_update_sti_subclass_type
+ assert_instance_of Topic, topics(:first)
+
+ reply = topics(:first).becomes!(Reply)
+ assert_instance_of Reply, reply
+ reply.save!
+ assert_instance_of Reply, Reply.find(reply.id)
+ end
+
def test_update_after_create
klass = Class.new(Topic) do
def self.name; 'Topic'; end
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 673dcfc1d3..486e7b80ff 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1160,10 +1160,11 @@ Even though Active Record lets you specify conditions on the eager loaded associ
However if you must do this, you may use `where` as you would normally.
```ruby
-Article.includes(:comments).where("comments.visible" => true)
+Article.includes(:comments).where(comments: { visible: true })
```
-This would generate a query which contains a `LEFT OUTER JOIN` whereas the `joins` method would generate one using the `INNER JOIN` function instead.
+This would generate a query which contains a `LEFT OUTER JOIN` whereas the
+`joins` method would generate one using the `INNER JOIN` function instead.
```ruby
SELECT "articles"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "articles" LEFT OUTER JOIN "comments" ON "comments"."article_id" = "articles"."id" WHERE (comments.visible = 1)
@@ -1171,7 +1172,19 @@ This would generate a query which contains a `LEFT OUTER JOIN` whereas the `join
If there was no `where` condition, this would generate the normal set of two queries.
-If, in the case of this `includes` query, there were no comments for any articles, all the articles would still be loaded. By using `joins` (an INNER JOIN), the join conditions **must** match, otherwise no records will be returned.
+NOTE: Using `where` like this will only work when you pass it a Hash. For
+SQL-fragments you need use `references` to force joined tables:
+
+```ruby
+Article.includes(:comments).where("comments.visible = true").references(:comments)
+```
+
+If, in the case of this `includes` query, there were no comments for any
+articles, all the articles would still be loaded. By using `joins` (an INNER
+JOIN), the join conditions **must** match, otherwise no records will be
+returned.
+
+
Scopes
------