将列添加到表并修复Rails中现有记录的值

Hom*_*ith 17 migration ruby-on-rails

我想在我的"订单"表中添加一个名为"payment_type"的列.

这是我到目前为止的迁移:

def change
  add_column :orders, :payment_type, :string
end
Run Code Online (Sandbox Code Playgroud)

我希望payment_type保持当前在DB中的所有记录的值"normal".但是,不是为了将来的记录.我希望将来的记录没有默认值.我怎样才能做到这一点?

Mar*_*n M 37

由于您只想为所有现有记录设置值,您可以使用update_all,这比循环所有订单实例要快得多,因为它只使用数据库语句而不会实例化所有订单:

class Order < ActiveRecord::Base
end

def up
  add_column :orders, :payment_type, :string
  Order.reset_column_information
  Order.update_all(payment_type: 'normal')
end

def down
  remove_column :orders, :payment_type
end
Run Code Online (Sandbox Code Playgroud)

update_all 不会调用任何验证或触发器.

  • 我建议不要使用主Order类,而应该在迁移中定义存根Order类,否则如果Order类不再存在,迁移将在以后停止工作. (8认同)

eug*_*bin 5

我认为最简单的方法是:

  class AddStateToSites < ActiveRecord::Migration[5.1]
      def up
        add_column :sites, :state, :string, default: :complete # sets default value for existed records
        change_column :sites, :state, :string, default: nil # changes default value for next
      end

      def down
        remove_column :sites, :state
      end
    end
Run Code Online (Sandbox Code Playgroud)

然后在控制台中检查它:

>> Site.last.state
  Site Load (0.6ms)  SELECT  "sites".* FROM "sites" ORDER BY "sites"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> "complete"
>> Site.new.state
=> nil
Run Code Online (Sandbox Code Playgroud)