У меня есть немного проблемы с постоянным объемом в смешивании модулей. Скажем, у меня есть что-то вроде этого
module Auth
USER_KEY = "user" unless defined? USER_KEY
def authorize
user_id = session[USER_KEY]
def
end
Константа USER_KEY должна принять значение по умолчанию "пользователю", если она уже не определяется. Теперь я мог бы смешать это в несколько мест, но в одном из тех мест USER_KEY должен отличаться, таким образом, у нас могло бы быть что-то вроде этого
class ApplicationController < ActionController::Base
USER_KEY = "my_user"
include Auth
def test_auth
authorize
end
end
Я ожидал бы, что USER_KEY будет "my_user" при использовании в авторизовывают, так как он уже определяется, но это - все еще "пользователь", взятый из определения модулей USER_KEY. У кого-либо есть какая-либо идея, как добраться, авторизовывают для использования версии классов USER_KEY?
USER_KEY
, который вы объявили (даже условно) в Auth
, во всем мире известен как Auth :: USER_KEY
.Он не «смешивается» с включением модулей, хотя включение модулей может ссылаться на ключ неполным образом.
Если вы хотите, чтобы каждый включающий модуль (например, ApplicationController
) мог определять свой собственный USER_KEY
, попробуйте следующее:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
unless base.const_defined?(:USER_KEY)
base.const_set :USER_KEY, Auth::DEFAULT_USER_KEY
end
end
def authorize
user_id = session[self.class.const_get(:USER_KEY)]
end
end
class ApplicationController < ActionController::Base
USER_KEY = 'my_user'
include Auth
end
Если вы собираетесь перейти ко всему этому проблема, однако, вы могли бы просто сделать его методом класса:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
base.extend Auth::ClassMethods
base.send :include, Auth::InstanceMethods
end
module ClassMethods
def user_key
Auth::DEFAULT_USER_KEY
end
end
module InstanceMethods
def authorize
user_id = session[self.class.user_key]
end
end
end
class ApplicationController < ActionController::Base
def self.user_key
'my_user'
end
end
или аксессором уровня класса:
module Auth
DEFAULT_USER_KEY = 'user'
def self.included(base)
base.send :attr_accessor :user_key unless base.respond_to?(:user_key=)
base.user_key ||= Auth::DEFAULT_USER_KEY
end
def authorize
user_id = session[self.class.user_key]
end
end
class ApplicationController < ActionController::Base
include Auth
self.user_key = 'my_user'
end
Константы не имеют глобальной области видимости в Ruby. Константы могут быть видны из любой области, но вы должны указать, где должна быть найдена константа. Когда вы начинаете новый класс, модуль или def, вы начинаете новую область видимости, и если вам нужна константа из другой области, вы должны указать, где ее найти.
X = 0
class C
X = 1
module M
X = 2
class D
X = 3
puts X # => 3
puts C::X # => 1
puts C::M::X # => 2
puts M::X # => 2
puts ::X # => 0
end
end
end