Вопрос

I have this STI implementation:

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

I've added the following to the Instruction class:

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? 

=========

My database table appears to be storing the subclass names properly in its type column, and I've verified that the subclasses are loaded:

(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)

===========

the method get_view is called in the create method of Instruction.rb. The thinking is that each of these specific instructions can have their own view. get_view is a little bit of metaprogramming to put together the right view to call.

problem: when I call get_view on an Instruction that has clearly been instantiated and saved as a subclass, it's not calling the subclass method but instead calling the base class:

[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">

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

This is my first posting to Stack Overflow after years of lurking, so please deflower me gently. Cheers.

Это было полезно?

Решение

By looking at the output it looks like you are calling a method on an Instruction instance. As all SCreateWebPage instances are Instruction instances they can be Instruction instances regardless of a type column value. So you should double check that you are performing SCreateWebPage.find(id) and not Instruction.find(id).

Sometimes I use #becomes in abstract methods in order not to worry about types and not to perform additional queries:

class Instruction
  def get_view
    self.becomes(self.type.constantize).get_view
  end
end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top