Search code examples
ruby-on-railsrubyinheritancemethodssuperclass

Ruby: Mildly 'exotic' inheritance doesn't work?


I would like to factor a bunch of common code from subclasses into a superclass method. The superclass method must refer to a nonexistent (in the superclass) method that will be defined in the subclasses. But I can't get this to work.

This is one try out of many multiple variations I have tried:

class Superclass
    def chunk_of_code
        # <code...>
        nonexistant_superclass_method_defined_in_subclass params
        # <more code...>
    end
end

class Subclass < Superclass
    def nonexistant_superclass_method_defined_in_subclass params
        # whatever...
    end
end

Subclass.new.chunk_of_code params

This doesn't work. Other variations don't work either. Is this kind of coding possible in Ruby (I thought it was)? I did this kind of thing all the time working in Smalltalk.

Any way to achieve what I want? Please avoid advising me to use "mix-ins" or "modules," as I'd just like to just learn and use Ruby's inheritance for right now.

*Running latest version of Ruby.

Thanks.

EDIT: This is in a Rails app. The superclass is ApplicationController.

EDIT: Here is actual code from one of many iterations I've tried to do this. This particular example craps out with "undefined method `each' for nil:NilClass" in the view, apparently because the whole thing is running in the context of the super (where it isn't defined) instead of the sub, or at least that's my interpretation:

class ApplicationController < ActionController::Base
    protect_from_forgery
    before_filter :authenticate_registration!

    # models and x defined in subclass
    def index
        models = x.where registration_id: current_registration.id

        respond_to do |format|
            format.html # index.html.erb
            format.json { render json: models }
        end
    end
    # more code here...
    # ...
end

class PositionsController < ApplicationController
    def x
        Position
    end

    def models= blah
        @positions = blah
    end

    # more code here...
    # ...
end

Solution

  • Your error is actually nothing to do with inheritance and is on this line

    models = x.where registration_id: current_registration.id
    

    This is potentially ambiguous: does this mean call the method models= or does it mean assign to a local variable called models? In this (and similar) situation ruby assumes you're trying to deal with the local variable. If you want to call the method instead you need to do

    self.models = x.where registration_id: current_registration.id
    

    Since you models= method doesn't get called, @positions is nil and I assume your view tries to use it.

    You might also be interested in gems such as make_resourceful that handle this common controller stuff.