Ruby on rails Rails 3.1:can';t在添加列的同一迁移中写入该列

Ruby on rails Rails 3.1:can';t在添加列的同一迁移中写入该列,ruby-on-rails,ruby-on-rails-3,activerecord,rails-activerecord,rails-migrations,Ruby On Rails,Ruby On Rails 3,Activerecord,Rails Activerecord,Rails Migrations,我有一个add_列迁移,可以正常运行。但是,在运行它并启动控制台之后,我会发现first_name和last_name列完全为空。我试着使用save

我有一个add_列迁移,可以正常运行。但是,在运行它并启动控制台之后,我会发现first_name和last_name列完全为空。我试着使用
save
class UserAddFirstNameAndLastName < ActiveRecord::Migration
  def change
    # add column first name, last name string
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string

    User.all.each do |u|
      u.first_name = 'first name'
      u.last_name = 'last name'
      u.save
    end
  end
end
class UserAddFirstName和LastName
我还认为这可能是一些类加载问题,因此我插入了行
User
,以强制用户类在循环之前重新加载。没有骰子

当我将其分为两次迁移时,达到了预期的效果。有人对此有解释吗?我发誓我甚至在过去的迁移中在同一个项目中做过这件事


其他注意事项:Desive for user engine,在运行迁移之前将新列添加到用户类中的
attr\u accessible

在迁移运行之前,您正在加载用户类,因此
user
对其自身结构有点困惑。解决方案是在添加列后调用:

重置有关列的所有缓存信息,这将导致在下一个请求中重新加载这些列

此方法最常见的使用模式可能是在迁移中,即在创建表之后,您希望用一些默认值填充它

这一部分也可能值得一看

尝试回滚并使用如下迁移:

def change
  # add column first name, last name string
  add_column :users, :first_name, :string
  add_column :users, :last_name, :string

  User.reset_column_information

  User.all.each do |u|
    u.first_name = 'first name'
    u.last_name = 'last name'
    u.save
  end
end
# 1: Don't touch Model before the new columns.
def change
  add_column :models, :some_column, :string
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end

# 2: Pull in Model before adding the new columns.
def change
  puts Model.all.count
  add_column :models, :some_column, :string
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end

# 3: Pull in Model before adding the new columns but use reset_column_information
def change
  puts Model.all.count
  add_column :models, :some_column, :string
  Model.reset_column_information
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end
我通过三次迁移对此进行了检查,如下所示:

def change
  # add column first name, last name string
  add_column :users, :first_name, :string
  add_column :users, :last_name, :string

  User.reset_column_information

  User.all.each do |u|
    u.first_name = 'first name'
    u.last_name = 'last name'
    u.save
  end
end
# 1: Don't touch Model before the new columns.
def change
  add_column :models, :some_column, :string
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end

# 2: Pull in Model before adding the new columns.
def change
  puts Model.all.count
  add_column :models, :some_column, :string
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end

# 3: Pull in Model before adding the new columns but use reset_column_information
def change
  puts Model.all.count
  add_column :models, :some_column, :string
  Model.reset_column_information
  Model.all.each { |m| m.some_column = 'pancakes'; m.save }
end
第一个可以正常工作,第二个可以添加
一些列
,但保留空值,第三个也可以工作


我猜应用程序初始化(可能来自designe)中的某些内容导致加载用户及其模式,然后添加一列。但是,很显然,用户只知道新列的一部分,因为
u.first\u name
调用起作用,但用户内部缓存了一些东西,以防止将属性写入数据库。

确认这是一个问题,但有一个警告。我刚刚在一次迁移中使用了您的第一个和第三个示例。第一个没有保存到数据库。我对我们的DB文件夹进行了grep,以前我是对的——我有一些旧的迁移,保存方式如下。我们在项目中添加的内容导致模型在迁移之前预加载…我怀疑可能是
活动的\u重新加载
gem。我们还没有升级到Rails 3.2,但我注意到这是一个标准特性。如果我有时间的话,我希望通过测试来确认/反驳这一点。@Eric:初始化中有一些东西正在预加载模型类。(1) 为我工作,因为我的初始化中没有预加载任何内容;
在(2)和(3)中放置Model.all.count
,这只是模拟环境中正在进行的预加载的一种简单方法<代码>活动\u重新加载
听起来像是可疑的。如果在一次迁移中更改并使用模型,则添加
reset\u column\u信息
可能是一个好习惯。@KeesBriggs我刚刚用Rails 4.2.4检查了
reset\u column\u信息
方法,效果很好。对您来说会发生什么?mu太短了,它有一个非常好的答案来解释正在发生的事情和要做的事情,但我也建议将这两种迁移划分为不同的迁移。在一个中创建列,在另一个中填充。这可以防止您看到的问题,并使回滚不那么容易出错。