Rails STI:子类方法没有按预期调用



我有这个STI实现:

class Instruction < ActiveRecord::Base
  def get_view
    return "I'm a pseudo abstract base method!"
  end
end
class SCreateWebPage < Instruction
  def get_view
    return "I'm doing terribly important things!"
  end
end

我在指令类中添加了以下内容:

def self.inherited(child)
    child.instance_eval do
      def model_name
        Instruction.model_name
      end
    end
    super
  end
%w(S_create_web_page).each {|r| require_dependency r } if Rails.env.development? 

===========

我的数据库表似乎在其类型列中正确地存储了子类名称,并且我已经验证了子类是否已加载:

(rdb) Module.const_get("SCreateWebPage")
SCreateWebPage(id: integer, name: string, code: string, skwerkflow_id: integer, created_at: datetime, updated_at: datetime, factory_id: integer, type: string)

================

方法get_view是在Instruction.rb的create方法中调用的。其思想是,这些特定指令中的每一条都可以有自己的视图。get_view是一种元编程,用于组合要调用的正确视图。

问题:当我对一条显然已经实例化并保存为子类的指令调用get_view时,它不是调用子类方法,而是调用基类:

[30, 39] in /Users/alexedelstein/dev/skwerl/app/models/instruction.rb
   30    end
   31  
   32    #overridden by subclass to help controller find the right class-specific view.
   33    def get_view
   34      debugger
=> 35        return "I'm a pseudo abstract base method!"
   36      return nil
   37    end
   38  
   39    debugger
(rdb:13) self
#<Instruction id: 87, name: "Create Web Page", code: nil, skwerkflow_id: 38, created_at: "2013-07-18 01:00:40", updated_at: "2013-07-18 01:00:40", factory_id: nil, type: "SCreateWebPage">

===============

这是我潜伏多年后第一次发布到Stack Overflow,所以请温柔地解除我的限制。干杯

通过查看输出,看起来就像是在指令实例上调用方法。由于SCreateWebPage的所有实例都是指令实例,因此无论类型列值如何,它们都可以是Instruction。因此,您应该仔细检查是否正在执行SCreateWebPage.fund(id)而不是Instruction.fund(id).

有时,为了不担心类型和不执行额外的查询,我在抽象方法中使用#because:

class Instruction
  def get_view
    self.becomes(self.type.constantize).get_view
  end
end

最新更新