Question

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.

Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top