我有一个帖子,迁移会向其中添加新属性和表格列short_url
。此属性由用户提供,如果留空,则自动创建:
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
在迁移中,我想浏览所有帖子并创建并保存short_url。
问题:由于create_short_url方法的私有范围,Post.find(:all).each {|post| post.create_short_url}
中的self.up
无效。
问题:通过帖子和update!
循环播放它们不会调用before_create :create_short_url
,因为它不是在创建之前。迁移后,我宁愿没有任何before_update
挂钩:我不需要在更新时更改任何内容。
你会如何解决这个问题?将random_string()
及相关方法复制到迁移中?将特定的迁移帮助程序方法添加到Post
?
答案 0 :(得分:1)
只需使用Object方法send
(它不会检查protected / private)。
Post.all.each do |post|
post.send :create_short_url
post.save!
end
另一种选择是(但这可能会干扰之后在同一个Ruby进程中运行的其他迁移):
Post.before_save :create_short_url
Post.all.each(&:save!)
可见性提示:大多数情况下,您的真正含义是protected
(请参阅here)。在这种情况下,我建议使用protected
代替private
。