Rails STI:调用子方法

时间:2010-08-20 15:29:20

标签: ruby-on-rails ruby sti

我有类似的东西

class Reply < AR::Base
end

class VideoReply < Reply
  def hello
    p 'not ok'
  end
end

class PostReply < Reply
  def hello
    p 'ok'
  end
end

...

所以当我创建对象时:

# params[:reply][:type] = "VideoReply"
@reply = Reply.new(params[:reply])

如何调用子方法(在本例中为VideoReply::hello)?

UPD: 我可以想象只有非常愚蠢的解决方案:

@reply = Reply.new(params[:reply])
eval(@reply.type).find(@reply.id).hello

但我认为这并不酷!)

1 个答案:

答案 0 :(得分:2)

当您处理基于STI的模型时,如果您不小心,则在创建它们时会遇到问题。只要您使用基类查找,就应该自动检索它们。

您需要的是首先创建合适的模型,其余的都可以。在您的模型或控制器中定义有效类的列表:

REPLY_CLASSES = %w[ Reply VideoReply PostReply ]

然后您可以在创建对象之前使用它来验证类型:

# Find the type in the list of valid classes, or default to the first
# entry if not found.
reply_class = REPLY_CLASSES[REPLY_CLASSES.index(params[:reply][:type]).to_i]

# Convert this string into a class and build a new record
@reply = reply_class.constantize.new(params[:reply])

这应该使用适当的类创建回复。此时方法应该按照需要工作。