Reputation: 47
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
Upvotes: 0
Views: 138
Reputation: 1501
Over on the model side of Rails, I routinely use:
class GenericModel < ActiveRecord::Base
self.abstract_class = true
# define all the generic behavior methods/ model stubs you want.
# model-specific classes can override to their hearts content
# or use the inherited implementation
end
class Feature < GenericModel
# model specific methods, and/or overrides
end
and I use a
class GenericController
# basic show implementation for example
def show
@object = params[:controller].singularize.camelcase.constantize.find(params[:id])
respond_to do |format|
format.pdf { render :layout => false }
format.html # show
format.xml { render :xml => @object.to_xml }
end
end
end
If a specific model's show behavior isn't any different than generic, then that method doesn't appear in that 'model'_controller.rb.
Upvotes: 0
Reputation: 84182
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.
Upvotes: 1
Reputation: 184
A way to do this is to define it in the parent and raise NotImplementedError
as the behavior of the method. By the way what you are trying to do is create an abstract class, which is facilitated more in certain other languages like Java.
Upvotes: -1
Reputation: 15779
The only error you have here is the definition of the chunk_of_code
. This method has to accept some formal parameter, like:
def chunk_of_code params
And then you're free to call it:
params = 'something'
Subclass.new.chunk_of_code params
Upvotes: 3