Rudiney Franceschi
Rudiney Franceschi

Reputation: 138

Call a class method with a multi level Module structure in Ruby

I have some modules to be included in my controller classes. These modules define before_filter:

module BasicFeatures
  def filter_method
    ...
  end
  def self.included(base)
    base.before_filter(:filter_method)
    ...
  end
end

module AdvancedFeatures
  include BasicFeatures
  ...
end

And the classes:

class BasicController < ApplicationController
    include BasicFeatures
end

class AdvancedController < ApplicationController
    include AdvancedFeatures
end
  1. When BasicFeatures module is included in AdvancedFeatures module, there are no before_filter methods in it.
  2. The AdvancedController didn't get the before_filter call.

I need both my controllers to get the before_filter without any code duplication. I don't know if I am using the best approach so, I'm open to any suggestion.

Upvotes: 4

Views: 1207

Answers (2)

usha
usha

Reputation: 29349

You can try this. Instead of including the module in AdvancedFeatures, You can include the BasicFeatures module on the class including AdvancedFeatures

module BasicFeatures
    def filter_method
      #code....
    end

    #some others basic methods...

    def self.included(base)
      base.before_filter(:filter_method)
      #some other class method calls
    end
end

module AdvancedFeatures
  def self.included klass
    klass.class_eval do
      include BasicFeatures
    end
  end

  #some advanced methods
end

Upvotes: 0

coreyward
coreyward

Reputation: 80041

This is why ActiveSupport::Concern was created.

module BasicFeatures
  extend ActiveSupport::Concern

  included do
    before_filter :require_user
  end

  def this_is_an_instance_method
    'foo'
  end

  module ClassMethods
    def this_is_a_class_method
      'bar'
    end
  end
end

class SomeClass
  include BasicFeatures
end

SomeClass.new.this_is_an_instance_method #=> 'foo'

You can also nest them — that is, create concerns that include concerns — and everything will work as expected. And here are the docs.

Upvotes: 5

Related Questions