use*_*536 8 migration activerecord ruby-on-rails rails-migrations rails-activerecord
我正在编写迁移以向表中添加列.列的值取决于另外两个现有列的值.最好/最快的方法是什么?目前我有这个,但不确定它是否是最好的方式,因为组表可能非常大.
class AddColorToGroup < ActiveRecord::Migration
def self.up
add_column :groups, :color, :string
Groups = Group.all.each do |g|
c = "red" if g.is_active && is_live
c = "green" if g.is_active
c = "orange"
g.update_attribute(:type, c)
end
end
def self.down
end
end
Run Code Online (Sandbox Code Playgroud)
Jim*_*art 15
从这样的迁移中引用模型通常是个坏主意.问题是迁移按顺序运行并随着时间的推移更改数据库状态,但您的模型根本没有版本化.无法保证在编写迁移时存在的模型将来仍与迁移代码兼容.
例如,如果您将来更改is_active或is_live属性的行为,则此迁移可能会中断.对于新的模型代码,此旧迁移将首先运行,并且可能会失败.在这里的基本示例中,它可能不会出现,但是在添加字段并且验证无法运行之前,这已经让我在部署中烧毁了(我知道您的代码正在跳过验证,但通常这是一个问题).
我最喜欢的解决方案是使用纯SQL进行此类迁移.看起来你已经考虑过了,所以我假设你已经知道该怎么做了.
另一个选择,如果你有一些毛茸茸的业务逻辑或只是希望代码看起来更像Railsy,那就是在迁移文件本身写入迁移时包含模型的基本版本.例如,您可以将此类放在迁移文件中:
class Group < ActiveRecord::Base
end
Run Code Online (Sandbox Code Playgroud)
在您的情况下,仅此一点可能足以保证模型不会破坏.假设active并且live此时表中是布尔字段(因此将来会运行此迁移),您根本不需要任何其他代码.如果您有更复杂的业务逻辑,则可以将其包含在此特定于迁移的模型版本中.
您甚至可以考虑将模型中的整个方法复制到迁移版本中.如果你这样做,请记住,如果你的应用程序有可能在将来发生变化,你也不应该从那里引用你的应用程序中的任何外部模型或库.这包括gems甚至可能是一些核心的Ruby/Rails类,因为gems中的API破坏性变化非常普遍(我正在看着你,Rails 3.0,3.1和3.2!).
我强烈建议您总共进行三个查询。始终利用数据库而不是循环遍历数组中的一堆项目。我认为这样的事情是可行的。
出于编写本文的目的,我假设 is_active 检查一个活动字段,其中 1 处于活动状态。我假设现场也一样。
Rails 3 方法
class AddColorToGroup < ActiveRecord::Migration
def self.up
add_column :groups, :color, :string
Group.where(active: 1, live: 1).update_all(type: "red")
Group.where(active: 1, live: 0).update_all(type: "green")
Group.where(active: 0, live: 0).update_all(type: "orange")
end
end
Run Code Online (Sandbox Code Playgroud)
请随意在此处查看 update_all 的文档。
Rails 2.x 方法
class AddColorToGroup < ActiveRecord::Migration
def self.up
add_column :groups, :color, :string
Group.update_all("type = red", "active = 1 AND live = 1")
Group.update_all("type = red", "active = 1 AND live = 0")
Group.update_all("type = red", "active = 0 AND live = 0")
end
end
Run Code Online (Sandbox Code Playgroud)
我会在一个
after_create
# or
after_save
Run Code Online (Sandbox Code Playgroud)
在您的 ActiveRecord 模型中:
class Group < ActiveRecord::Base
attr_accessor :color
after_create :add_color
private
def add_color
self.color = #the color (wherever you get it from)
end
end
Run Code Online (Sandbox Code Playgroud)
或者在迁移中你可能需要执行一些如下的 SQL:
execute('update groups set color = <another column>')
Run Code Online (Sandbox Code Playgroud)
以下是 Rails 指南中的示例:
http://guides.rubyonrails.org/migrations.html#using-the-up-down-methods
| 归档时间: |
|
| 查看次数: |
6757 次 |
| 最近记录: |