【问题标题】:Setting different default values in rails migrations?在 Rails 迁移中设置不同的默认值?
【发布时间】:2012-09-27 01:50:18
【问题描述】:

我正在尝试编写迁移,它看起来像这样:

class AddStatusToWorks < ActiveRecord::Migration
  def self.up
    change_table :works do |t|
        t.string :status
    end
  end

  def self.down
    change_table :works do |t|
        t.remove :status
    end
  end
end

问题是,我想根据表中已有的布尔值“完成”为“状态”设置不同的默认值。如果完成 = true,则状态 =“完成”。如果没有,status = "work in progress." (我想要一个字符串而不是作为布尔值保持完整的原因是因为我希望那里能够有两个以上的状态可能性。)知道怎么做吗?我是否像这样在其中粘贴一个 if 语句

change_table :works do |t|
        t.string :status
           if (:complete == true)
               :value => "complete"
           else
               :value => "wip"
end

呃,看起来不太对劲。我用谷歌搜索了一下,发现你可以设置 :default 值,但这并不是我想要的。任何想法/帮助都会很可爱。谢谢!

【问题讨论】:

  • 所以要根据complete的当前值来初始化status?新行呢?
  • 呃...新行?抱歉,我在这方面有点不知所措。
  • 等等!你的意思是新行作为未来的数据库条目吗?在这些情况下,用户将在他们创建新作品时设置一个值。只是数据库中已经有很多条目,我想知道是否有自动设置它们的值的方法。
  • 是的,这就是我所说的新行
  • 嘿,我知道我错过了一些东西。但我最终明白了,这很重要,对吧?现在查看您的其他回复!

标签: ruby-on-rails ruby migration rails-migrations


【解决方案1】:

您根本不需要默认值,您只需要添加新列并为其赋值。像这样的东西应该可以工作:

def self.up
  change_table :works do |t|
      t.string :status
  end
  Works.reset_column_information
  Works.where(:complete => true).update_all(:status => 'complete')
  Works.where(:complete => [false, nil]).update_all(:status => 'wip')
end

有关reset_column_information 的信息,请参阅Migrations Guide

您也可以直接在数据库中执行此操作,但您必须注意不同的布尔表示(PostgreSQL 想要 't''f',MySQL 想要 10,SQLite 想要 1 和 @ 987654329@ 但 Rails 错误地使用了 't''f', ...):

t = connection.quote(true)
connection.execute(%Q{
  update works
  set status = case complete
    when #{t} then 'complete'
    else 'wip'
  end
})

【讨论】:

  • 因此您可以使用“where”来选择信息,而不是 if/else。哦,这看起来很棒,正是我正在寻找的。非常感谢!
  • 对,您使用where 告诉ActiveRecord 您要查找的内容,然后update_all 将其转换为数据库中的UPDATE ...
【解决方案2】:

请记住,创建记录时会立即创建默认值,因此还没有没有默认值的字段值。您可能希望将这种逻辑移动到您的模型中。也许在 ActiveRecord 回调中,即 before_validation 或 before_save。

【讨论】:

  • 啊……嗯。好的。所以基本上,创建没有 if 语句的表,然后在模型中,做这样的事情:def edit_status if self.complete = true self.status = "complete" else self.status = "wip" then before_save :edit_status 像那样?
  • welp,丢失了很多格式。嗯。无论如何,有没有办法直接在迁移中做到这一点?因为事情是我希望设置一次默认值,然后用户可以直接编辑它们。如果我使用 before_save,每次用户编辑任何关于 :works 的内容时都会触发吗?
猜你喜欢
  • 2010-10-27
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
相关资源
最近更新 更多