Rails 迁移设置布尔字段不起作用



我有一个迁移,它添加了一个布尔列并为一些行设置值。保存模型时,新值不会保存到数据库中。以下是代码的简化版本:

class AddSmartToStudent
def change
add_column :students, :smart, :boolean
Student.where(grade: 'A').each do |student|
student.smart = true
student.save!
end
end
end

提前感谢!

在迁移中,添加一个布尔列,然后在模型中使用它。不确定这是否可能——当迁移尚未结束但事务尚未提交时。Student模型可能还没有smart字段。

正如LuisSilva所建议的,您可以使用reset_column_information方法来刷新Student的列信息。但问题是迁移并不是为了处理数据。如果你想更改一些数据,最好在rake任务中进行。

如果出于某种原因,您必须在迁移中执行此操作,则可以在纯SQL查询中执行。对于PostgreSQL,它将是:

execute "UPDATE students SET smart='t' WHERE grade='A'"

尝试重置缓存的列信息,这将导致在下一次请求时重新加载这些列。

在所在的条款前执行此行

Student.reset_column_information

reset_column_formation

有两个问题我很清楚。

  1. 正如其他人所说,您正试图使用在同一迁移中添加的属性。安全的做法是像路易斯·席尔瓦的回答中解释的那样重置列信息。

  2. 第二个问题与使用def change有关,其中一些内容是不可逆的。变更方法中的所有内容都应该是可逆的。否则应使用def updef down

这里有两个选项可以解决您的问题:

  1. 使用CCD_ 10和CCD_。

    class AddSmartToStudent
    def up
    add_column :students, :smart, :boolean
    Student.reset_column_information
    Student
    .where(grade: 'A')
    .find_each { |student| student.update!(smart: true) }
    end
    def down
    remove_column :students, :smart
    end
    end
    
  2. 使用CCD_ 12。

    class AddSmartToStudent
    def change
    add_column :students, :smart, :boolean
    reversible do |change|
    change.up do
    Student.reset_column_information
    Student
    .where(grade: 'A')
    .find_each { |student| student.update!(smart: true) }
    end
    end
    end
    end
    

如果你不关心Rails回调、验证等,你也可以使用

Student.where(grade: 'A').update_all(smart: true)

作为的替代品

Student.where(grade: 'A').find_each { |student| student.update!(smart: true) }

这会用一个查询更新所有记录,但不会实例化记录,这意味着Rails回调、验证等不会运行。有关更多信息,请参阅update_all

最新更新