Question

Given the following:

class User; attr_accessor :roles; end

module RegisteredUser
  def default_context
    Submission
  end
end

module Admin
  def default_context
    Review
  end
end

current_user = User.new
current_user.roles = ["registered_user", "admin"]
current_user.roles.each do |role|
  role_module = role.gsub(/ /, '_').camelize
  if module_exists?(role_module)
    current_user.extend role_module.constantize
  end
end
context = self.extend current_user.default_context

Is there a way to set the priority of User#default_context? That is, can I say that the Admin#default_context always takes priority over RegisteredUser#default_context regardless of the order in which current_user is extended?

Was it helpful?

Solution

method_added is in Module.

I actually meant included, not extended, but both are also in Module.

The mechanism would revolve around doing something like this:

module Foo
  def self.included(base)
    base.extend(FooMethods)
  end

  module FooMethods
    def bar
      # Whatever
    end
  end
end

Inside Foo.included you can determine, based on arbitrary criteria, whether or not the methods in question should be added to base (the entity including the module).

In your case, you could check to see if a "higher priority" module was already included, or see if the module is the "higher priority" module. Based on that you'd decide whether or not to add the methods.

OTHER TIPS

Since an Admin is also a RegisteredUser, I would do

module Admin
  include RegisteredUser
  ...
end

and then only

current_user.extend Admin

I am not sure if this is the correct way. If Admin and RegisteredUser were classes, it would make sense making Admin inherit from RegisteredUser. In case of modules, dunno.

You cannot; in Ruby the order of module inclusion is the order in which modules are searched (after the current class, before parent classes). The only way to change the 'priority' is to include the modules in the order you want, or to move them to a parent class.

Although not pure Ruby, you can use the Remix library by banisterfiend to change module ordering (or unmixin a module, or...other things).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top