Ruby precedence of methods in objects extended with multiple modules
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?
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).