Объем констант в модулях Ruby

У меня есть немного проблемы с постоянным объемом в смешивании модулей. Скажем, у меня есть что-то вроде этого

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?

54
задан user204078 21 April 2010 в 12:41
поделиться

2 ответа

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
58
ответ дан 7 November 2019 в 07:53
поделиться

Константы не имеют глобальной области видимости в 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
41
ответ дан 7 November 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: