Dex
Dex

Reputation: 12759

Ruby Subclasses: Including Different Modules Based on Inheritance

I have two classes, Task and Subtask. Subtask varies very little from Task except for one important thing, it must include a different module.

The included modules, subtask_module and task_module, both have the same methods and aliases for my purposes, but internally they function a little differently once the included module extends its methods. There is no way around this for me because I'm using a plugin.

For instance, below, you see belongs_to in Task. belongs_to is extended from the included module, however its function differs slightly based on which module I include.

class Subtask < Task
  include subtask_module 
end

class Task
  include task_module

  # methods and aliases both classes use (defined in included file) 
  # but behavior changes based on
  # included file
  belongs_to :template    
end

What is the best way to do something like this? Right now it works as it is now. But it seems bloated because there will be unused things declared in Task that I don't need.

What is the best way?

Upvotes: 3

Views: 2238

Answers (1)

Joshua Cheek
Joshua Cheek

Reputation: 31786

You could either turn Task into a subclass also, then have each inherit from something common (using your names from above wherever possible)

class Task
  belongs_to :template    
end

class Subtask1 < Task
  include subtask_file 
end

# this used to be Task, now is Subtask2
class Subtask2 < Task
  include task_file
end

Or, you move the shared functionality out to its own module, then include that, and avoid superclass / subclass altogether (I would opt for this one).

module TaskShared
  belongs_to :template    
end

class Task
  include TaskShared
  include task_file
end

class Subtask
  include TaskShared
  include subtask_file 
end

(The belongs_to might give you difficulty. If so, try adding it in the included hook)

module TaskShared
  def self.included(klass)
    klass.belongs_to :template
  end
end

Note that there are some circumstances where this gets sticky, such as inheriting from ActiveRecord::Base classes.

Upvotes: 5

Related Questions