Рубиновый приоритет методов в объектах, расширенных несколькими модулями - PullRequest
1 голос
/ 30 ноября 2011

Учитывая следующее:

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

Есть ли способ установить приоритет User#default_context?То есть можно ли сказать, что Admin#default_context всегда имеет приоритет над RegisteredUser#default_context независимо от порядка, в котором current_user расширен?

Ответы [ 3 ]

2 голосов
/ 30 ноября 2011

method_added в Module.

Я на самом деле имел в виду included, а не extended, но оба они также в Module.

Механизм будет вращаться вокругделая что-то вроде этого:

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

  module FooMethods
    def bar
      # Whatever
    end
  end
end

Внутри Foo.included вы можете определить, основываясь на произвольных критериях, следует ли добавлять рассматриваемые методы в base (объект, включающий модуль).

В вашем случае вы можете проверить, был ли включен модуль с более высоким приоритетом, или посмотреть, является ли модуль модулем с более высоким приоритетом.Исходя из этого, вы решите, добавлять методы или нет.

1 голос
/ 30 ноября 2011

Вы не можете;в Ruby порядок включения модулей - это порядок поиска модулей ( после текущего класса, перед родительскими классами ).Единственный способ изменить приоритет - это включить модули в нужном вам порядке или переместить их в родительский класс.

Хотя это и не чистый Ruby, вы можете использовать Remix * 1006.* библиотека от banisterfiend для изменения порядка модулей (или размешивания в модуле, или ... других вещей).

1 голос
/ 30 ноября 2011

Поскольку администратор также является зарегистрированным пользователем, я бы сделал

module Admin
  include RegisteredUser
  ...
end

, а затем только

current_user.extend Admin

Я не уверен, что это правильный путь.Если бы Admin и RegisteredUser были классами, имело бы смысл заставить Admin наследоваться от RegisteredUser.В случае модулей, не знаю.

...