Rails 3.1: can't write to column in same migration that adds it

后端 未结 1 1755
一整个雨季
一整个雨季 2021-02-04 00:42

I had an add_column migration that would run fine. However, after running it and firing up a console, I would find the first_name and last_name columns completely empty. I tri

相关标签:
1条回答
  • 2021-02-04 01:08

    You're loading the Users class somewhere before your migration runs so User is a little confused about its own structure. The solution is to call reset_column_information after adding your column:

    Resets all the cached information about columns, which will cause them to be reloaded on the next request.

    The most common usage pattern for this method is probably in a migration, when just after creating a table you want to populate it with some default values

    The Using Models in Your Migrations section of the Migrations Guide might be worth a look as well.

    Try rolling back and using a migration like this:

    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
    

    I checked this with three migrations like this:

    # 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
    

    The first one works just fine, the second one adds some_column but leaves it with NULL values, the third one also works.

    I'd guess that something in your application initialization (possibly from Devise) is causing User and its schema to be loaded, then you add a column. But, apparently, User only partly knows about the new column as the u.first_name call works but something is cached inside User to prevents the attribute from being written to the database.

    0 讨论(0)
提交回复
热议问题