61

I'm creating a bunch of migrations, some of which are standard "create table" or "modify table" migrations, and some of which modify data. I'm using my actual ActiveRecord models to modify the data, a la:

Blog.all.each do |blog|
  update_some_blog_attributes_to_match_new_schema
end

The problem is that if I load the Blog class, then modify the table, then use the Blog class again, the models have the old table definitions, and cannot save to the new table. Is there a way to reload the classes and their attribute definitions so I can reuse them?

brian d foy
  • 129,424
  • 31
  • 207
  • 592
James A. Rosen
  • 64,193
  • 61
  • 179
  • 261

3 Answers3

143

The answer is yes!

Blog.reset_column_information
James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
  • 2
    Watch out for models with relationships. If `class Blog; belongs_to Owner; end`, then you may need to `Owner.reset_column_information` in addition to Blog. – Gavin Brock Jun 05 '12 at 05:33
  • 4
    Reset all the columns! `ActiveRecord::Base.descendants.each{|c| c.reset_column_information}` – rude-n8 Jul 09 '14 at 00:33
  • 1
    Throw `Rails.application.eager_load!` in front of any calls to descendants to fix issues with non-autoloaded models – elju Nov 25 '15 at 15:30
  • I wonder why this is not triggered automatically after every schema update, since migrations are not very time-critical. – juffel May 04 '16 at 14:04
5

I always used new models in migrations

    MyBlog < ActiveRecord::Base
      set_table_name 'blogs'
    end

    def self.up
      MyBlog.all.each do |blog|
        update_some_blog_attributes_to_match_new_schema
      end
    end

But Blog.reset_column_information is more convenient.

Vitalie
  • 736
  • 3
  • 9
3

Create new instances:


Old_blogs = Blog.all

# change/modify db table in here

New_blogs = Blog.all # this should be reloaded or you could use the .reload on this

# change information, load old into new

ex.

Old_blogs.each do |blog|
  New_blogs.find(blog.id).title = blog.title
end
rohin-arka
  • 779
  • 4
  • 10
Jon Smock
  • 9,451
  • 10
  • 46
  • 49