Rails 新迁移未更新旧数据
Rails new migrations not updating old data
我有一个名为 Article 的模型。这个模型有一个名为 duration 的属性,它是一个字符串。持续时间可以是早上、下午、傍晚和晚上。
例如,文章对象如下所示:
#<Article id: 1, created_at: "2015-09-22 08:00:08", updated_at: "2015-09-22 08:00:08", duration: "morning">
由于持续时间具有相似的属性,我创建了一个称为持续时间的基础 class 和继承的 classes 作为早晨、下午、傍晚和夜晚。
一个时间段内可以有很多篇文章。但是一篇文章只能有一个持续时间。所以,我有 has_many
和 belongs_to
关联:
app/model/duration.rb
class Duration < ActiveRecord::Base
has_many :articles
end
app/model/article.rb
class Article < ActiveRecord::Base
belongs_to :duration
end
其他继承的class是:
app/model/duration/morning.rb
class Morning < Duration
end
等等 afternoon.rb
、evening.rb
和 night.rb
。
我已经有了创建持续时间的迁移 table。要将字段 type
添加到持续时间,我有一个名为 add_type_to_duration.rb
的迁移
AddTypeToDuration < ActiveRecord::Migration
def change
add_column :durations, :type, :string
end
end
我有另一个名为 add_duration_ref_to_articles.rb
的迁移文件来添加参考
class AddDurationRefToArticles < ActiveRecord::Migration
def change
add_reference :articles, :duration, index:true
end
end
我有另一个迁移以在 add_initial_durations.rb
中创建新的持续时间
class AddInitialDurations < ActiveRecord::Migration
def change
Morning.create
Afternoon.create
Evening.create
Night.create
end
end
现在我想更新旧数据以适应新的迁移。所以,我有另一个名为 update_articles_to_have_duration.rb
的迁移
class UpdateArticlesToHaveDuration < ActiveRecord::Migration
def change
morning = Duration.find_by_type("Morning")
Article.where(duration: "morning").find_each do |article|
article.update!(duration_id: morning.id)
end
end
end
现在,当我 运行 迁移所有文章时,曾经有 duration = morning
,现在有 duration_id = nil
。但是,当我运行上次迁移时再次用rake db:migrate:redo step:1
,则文章已经正确duration_id。我认为迁移不正确 运行。但是,我在 运行 设置它们时没有收到任何错误。谁能告诉我我在这里做错了什么?
感谢您的帮助。
正如您所说 运行 第二次迁移时 duration_id
设置正确,第一次无法正常工作的唯一原因可能是迁移未 运行如您所示按顺序排列。
迁移文件上有 时间戳,当您执行 rake db:migrate
时,它们 运行 最旧。
查看迁移文件的时间戳以确保它们按照您的需要进行排序。
❯ rake db:migrate:status
database: ~/blog/db/development.sqlite3
Status Migration ID Migration Name
--------------------------------------------------
up 20150907015616 Create articles
down 20150907031746 Create comments
down 20150909034614 Devise create users
你可以使用上面的命令查看Migration Id并将其复制到运行一个接一个的迁移中,用以下命令验证我的假设:
❯ bin/rake db:migrate VERSION=20150907015616 VERSION=20150907031746 VERSION=20150909034614
如果迁移文件不遵循时间戳的时间顺序,您将不得不重新排序(最好删除并重新创建)迁移文件或转置其内容。
我有一个名为 Article 的模型。这个模型有一个名为 duration 的属性,它是一个字符串。持续时间可以是早上、下午、傍晚和晚上。
例如,文章对象如下所示:
#<Article id: 1, created_at: "2015-09-22 08:00:08", updated_at: "2015-09-22 08:00:08", duration: "morning">
由于持续时间具有相似的属性,我创建了一个称为持续时间的基础 class 和继承的 classes 作为早晨、下午、傍晚和夜晚。
一个时间段内可以有很多篇文章。但是一篇文章只能有一个持续时间。所以,我有 has_many
和 belongs_to
关联:
app/model/duration.rb
class Duration < ActiveRecord::Base
has_many :articles
end
app/model/article.rb
class Article < ActiveRecord::Base
belongs_to :duration
end
其他继承的class是:
app/model/duration/morning.rb
class Morning < Duration
end
等等 afternoon.rb
、evening.rb
和 night.rb
。
我已经有了创建持续时间的迁移 table。要将字段 type
添加到持续时间,我有一个名为 add_type_to_duration.rb
AddTypeToDuration < ActiveRecord::Migration
def change
add_column :durations, :type, :string
end
end
我有另一个名为 add_duration_ref_to_articles.rb
的迁移文件来添加参考
class AddDurationRefToArticles < ActiveRecord::Migration
def change
add_reference :articles, :duration, index:true
end
end
我有另一个迁移以在 add_initial_durations.rb
中创建新的持续时间class AddInitialDurations < ActiveRecord::Migration
def change
Morning.create
Afternoon.create
Evening.create
Night.create
end
end
现在我想更新旧数据以适应新的迁移。所以,我有另一个名为 update_articles_to_have_duration.rb
class UpdateArticlesToHaveDuration < ActiveRecord::Migration
def change
morning = Duration.find_by_type("Morning")
Article.where(duration: "morning").find_each do |article|
article.update!(duration_id: morning.id)
end
end
end
现在,当我 运行 迁移所有文章时,曾经有 duration = morning
,现在有 duration_id = nil
。但是,当我运行上次迁移时再次用rake db:migrate:redo step:1
,则文章已经正确duration_id。我认为迁移不正确 运行。但是,我在 运行 设置它们时没有收到任何错误。谁能告诉我我在这里做错了什么?
感谢您的帮助。
正如您所说 运行 第二次迁移时 duration_id
设置正确,第一次无法正常工作的唯一原因可能是迁移未 运行如您所示按顺序排列。
迁移文件上有 时间戳,当您执行 rake db:migrate
时,它们 运行 最旧。
查看迁移文件的时间戳以确保它们按照您的需要进行排序。
❯ rake db:migrate:status
database: ~/blog/db/development.sqlite3
Status Migration ID Migration Name
--------------------------------------------------
up 20150907015616 Create articles
down 20150907031746 Create comments
down 20150909034614 Devise create users
你可以使用上面的命令查看Migration Id并将其复制到运行一个接一个的迁移中,用以下命令验证我的假设:
❯ bin/rake db:migrate VERSION=20150907015616 VERSION=20150907031746 VERSION=20150909034614
如果迁移文件不遵循时间戳的时间顺序,您将不得不重新排序(最好删除并重新创建)迁移文件或转置其内容。