开发者

In a migration: how to loop through Models and execute a private method in Model

I have a Post, to which a migration adds a new attribute and table column short_url. This attribute is either provided by the user, or, if left blank, automatically created:

class Post < ActiveRecord::Base
  before_create :create_short_url

  private
  def create_short_url
    if short_url.blank? || already_exists?(short_url)
      write_attribute :short_url, random_string(6)
    end
  end
  def random_string(length)
   #innards are irrelevant for this question
  end
end

In the migration, I want to run through all posts and have the short_url created and saved.

problem: Post.find(:all).each {|post| post.create_short_url} in the self.up is not possibl开发者_C百科e, due to the private scope of the create_short_url method.

problem: Looping through posts and update!-ing them does not invoke the before_create :create_short_url, because it is not before create. Once migrated, I prefer to not have any before_update hooks in place: I don't need to change anything on update.

How would you tackle this? Copy over the random_string() and associated methods to the migration? Add specific migration helper methods to the Post?


Just use the Object method send (it doesn't check protected/private).

Post.all.each do |post|
  post.send :create_short_url
  post.save!
end

An alternative would be (but that could interfere with other migrations running in the same Ruby-process after that):

Post.before_save :create_short_url
Post.all.each(&:save!)

Visibility tip: Most of the time what you really mean is protected (see here). I recommend to use protected instead of private in this case.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜