sqlite Rails新迁移不更新旧数据

sycxhyv7  于 2023-11-21  发布在  SQLite
关注(0)|答案(2)|浏览(182)

我有一个名为Article的模型。这个模型有一个名为duration的属性,它是一个字符串。持续时间可以是上午,下午,晚上和晚上。
例如,article对象看起来像这样:

#<Article id: 1, created_at: "2015-09-22 08:00:08", updated_at: "2015-09-22 08:00:08", duration: "morning">

字符串
由于duration具有类似的属性,我创建了一个名为duration的基类,并继承了morning、afternoon、evening和night等类。
在一个duration中可以有很多文章。但是一个单独的文章只能有一个duration。所以,我有has_manybelongs_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


其他继承类有:

app/model/duration/morning.rb
class Morning < Duration
end


对于afternoon.rbevening.rbnight.rb,依此类推。
我已经有了创建duration表的迁移。

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_duration.rb中创建新的持续时间

class AddInitialDurations < ActiveRecord::Migration
  def change
    Morning.create
    Afternoon.create
    Evening.create
    Night.create 
  end
end


现在,我想更新旧数据以适应新的迁移。

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。我认为迁移没有正确运行。然而,我在运行它们时没有收到任何错误。任何人都可以告诉我这里做错了什么吗?
谢谢你的帮助

yqkkidmi

yqkkidmi1#

正如您所说的,第二次运行迁移时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


如果迁移文件不遵循时间戳的时间顺序,则必须重新排序(最好删除并重新创建)迁移文件或调换其内容。

xoshrz7s

xoshrz7s2#

我遇到了同样的问题,并使用MyModel.reset_column_information解决了它。

class UpdateArticlesToHaveDuration < ActiveRecord::Migration
  def change
    Article.reset_column_information

    morning = Duration.find_by_type("Morning")
    Article.where(duration: "morning").find_each do |article|
      article.update!(duration_id: morning.id)
    end
  end
end

字符串
它重置所有关于列的缓存信息,这将导致它们在下一个请求时重新加载。
此方法最常见的使用模式可能是在迁移中,即刚创建完一个表,就想用一些默认值填充它
有关更多详细信息,请参阅documentation

相关问题