在Rails迁移中更新属性值

时间:2015-04-21 00:44:45

标签: ruby-on-rails migration

我通过ActiveAdmin(http://activeadmin.info/)上传了超过100个食谱,其中包含以下属性:

class CreateRecipes < ActiveRecord::Migration
  def change
    create_table :recipes do |t|
      t.string :title
      t.string :description
      t.string :ingredients
      t.string :position

      t.timestamps
    end
  end
end

我需要将字符串中的位置更改为整数。我能够通过以下方式实现这一目标:

change_column :table_name, :column_name,  :integer  

stackoverflow:Rails migration for change column

问题在于我不知道怎么回去并用一个位置重新分配所有食谱(现在它是一个整数)。我基本上想从0开始一直到100。如果我创建一个新的配方,它会自动获得101的位置值。

有没有办法在不退回并单独更改每个食谱的情况下执行此操作?

2 个答案:

答案 0 :(得分:1)

听起来您最初要将:position设置为:id。你可以通过rails控制台这样做:

recipes = CreateRecipes.all
recipes.each do |recipe|
  recipe.position = recipe.id
end

然后,对于新的食谱,在您的模型(create_recipes.rb)中,您可以添加:

after_initialize :default_values
...
def default_values
  self.position ||= id
end

顺便说一下,这是处理默认值或初始值的一种很好的干净方法。有关详细信息,请参阅此优秀帖子How can I set default values in ActiveRecord?

答案 1 :(得分:0)

您可以将转化作为迁移本身的一部分自动运行。添加代码以将现有记录中的值转换为迁移。使用self.up和self.down为迁移的方向提供适当的转换代码:

class ChangeRecipePositionToInteger < ActiveRecord::Migration
  def self.up
    position_values = Hash[ Recipe.all.map{|r| [r.id, r.position]}]

    change_column :recipes, :position, :integer

    position_values.each_pair do |id, position_value|
      recipe = Recipe.find( id )
      recipe.position = position_value.to_i
      recipe.save
    end
  end

  def self.down
    position_values = Hash[ Recipe.all.map{|r| [r.id, r.position]}]

    change_column :recipes, :position, :string

    position_values.each_pari do |id, position_value|
      recipe = Recipe.find( id )
      recipe.position = position_value.to_s
      recipe.save
    end
  end
end