Editing models in migrations

Posted by topher
on Friday, July 13

In migrations, you can also edit your models. I have a Topic and a Post. A topic has many posts. The models are already created using previous migrations. Now I want to add 3 new fields to Topic—posts_count, replied_by, and replied_at.

Here is the migration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class AddCachedFieldsOnTopic < ActiveRecord::Migration
  class Topic < ActiveRecord::Base
    has_many :posts, :order => "posts.created_at"
  end
  class Post < ActiveRecord::Base; end
  
  def self.up
    add_column :topics, :posts_count, :integer, :default => 0
    add_column :topics, :replied_by, :integer
    add_column :topics, :replied_at, :datetime
    
    Topic.find(:all, :include => :posts).each do |topic|
      last_post = topic.posts.last
      posts_count = topic.posts.size
      Topic.update_all(["posts_count = ?, replied_by = ?, replied_at = ?", posts_count, last_post.user_id, last_post.created_at], ["id = ?", topic.id]) if last_post
    end
  end

  def self.down
    remove_column :topics, :posts_count
    remove_column :topics, :replied_by
    remove_column :topics, :replied_at
  end
end
Notes
  • posts_count will be used by rails for caching. In the post model, I’ll put :belongs_to :topic, :counter_cache => true. Set the default to 0.
  • You can actually get these fields through the association—topic.posts.count, topic.posts.last.user, topic.posts.last.created_at – but I’m adding it to Topic to avoid the additional queries.
  • I’m looking at (copying) the beast application.
Comments

Leave a response