如何在Ruby on Rails中动态分配模型进行.find操作?

4
我正在尝试创建单表继承(Single Table Inheritance)。
但是,控制器必须能够知道要查找或创建哪个类。这些基于另一个类。
例如,type = Letter 的 ContactEvent 需要从相应的模型 Letter 中获取属性。
以下是我尝试做的事情并遇到了问题,如下所示。
我需要能够动态调用分配 EventClass 的值,以便它可以是 Letter.find(:conditions =>) 或 Calls.find(:conditions =>),具体取决于控制器正在处理哪种类型。
  def new
    @contact_event = ContactEvent.new
    @contact_event.type = params[:event_type] # can be letter, call, postcard, email
    @contact_event.event_id = params[:event_id] # that ID to the corresponding Model
    @contact_event.contact_id = params[:contact]

    @EventClass = case
      when @contact_event.type == 'letter' then 'Letter'
      when @contact_event.type == 'call' then 'Call'
      when @contact_event.type == 'email' then 'Email'

以下是获取的信息:

    @event = @EventClass.find(@contact_letter.letter_id) #how do I make @EventClass actually the Class?SNAG

    # substitution of variables into the body of the contact_event
    @event.body.gsub!("{FirstName}", @contact.first_name)
    @event.body.gsub!("{Company}", @contact.company_name) 
    @evebt.body.gsub!("{Colleagues}", @colleagues.to_sentence)

    @contact_event.body = @event.body
    @contact_event.status = "sent"

  end
2个回答

12

这应该允许您动态调用一个模型,以下是使用User模型的示例:

model = "user".capitalize.constantize
model.all

使用示例:

model = params[:object_type].capitalize.constantize
if model.destroy_all(params[:object_id])
  render :json => { :success => true }
else
  render :nothing => true
end

实际上是动态的,而且只有一行代码。 - Archonic
这样做会引入任何负面后果吗? - karns

9
@event_class = case @contact_event.type
  when 'letter' then Letter
  when 'email'  then Email
  when 'call'   then Call
end

您需要分配类本身而不是字符串。您可以调用@event_class.find(whatever)。请注意以下几点:
单表继承得到支持,并由Rails自动处理。您可以让Letter、Email和Call继承ContactEvent。详见Rails API(Single Table Inheritance部分)。
您可以通过调用@contact_event_type.classify.constantize直接将字符串转换(例如,将“call”转换为Call)。
此外,请按照Ruby约定命名变量(@event_type而非@EventType),并检查case语句的使用方式。
希望这对您有用 :)

嗨,谢谢,我确实阅读了Single Table INheritance并且它得到了支持...但是我认为只有在明确调用子类时才能使用...但似乎我仍然需要确定那是什么...?或者我可以使用.class方法并通过它传递吗?有没有办法让我不必使用传递的:type变量? - Satchel
我不确定我理解你的模式是什么。电子邮件,电话和信函是ContactEvent的子类型吗(这对我来说似乎更合逻辑)?如果是这样,我认为你无法避免传递参数(或调用不同的URL),并且在控制器中,你只需调用@event_class.new,因为@even_class变量保存了类本身(记住,在Ruby中,类也是对象)。 - Chubas
在ContactEvent子类型中,实际的、联系人电子邮件、联系人电话和联系人信函都是必需的。然而,ContactEmail是通过传递给它的任何Email实例的Email.id来实例化的。将Email视为模板,而ContactEmail是使用特定联系人执行Email的过程。 - Satchel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接