Rails:包含模块,但维护模块名称?

时间:2013-05-11 21:42:01

标签: ruby-on-rails ruby actioncontroller

考虑这段代码

module Auth

  def sign_in(user)
    #some stuff
    session[:user_id] = user.id
  end

end

现在,我希望将其包含在我的应用程序控制器中。

ApplicationController < ActionController::Base
  include Auth
end

这使得我的所有控制器都可以使用sign_in方法。现在,为了清楚这不是一个控制器动作,我想保留名称,所以我的控制器读了

def sign_user_in
  # Some stuff
  Auth.sign_in(@user)
end

这显然不起作用,因为Rails将在Auth模块中查找类方法。所以问题是......是否可以将一个模块包含到控制器中,保留它的名称或命名空间,但仍然可以访问与控制器相同的范围? (在这种情况下,会话变量)。

到目前为止,我提出的最不好的方法是停止包含模块和ApplicationController,而是在调用这样的auth方法时传递应用程序控制器实例:

def current_user(controller)
  User.find(controller.session[:user_id])
end

使用self作为参数从控制器调用此方法有效。

1 个答案:

答案 0 :(得分:1)

试试这个吗?

对所有功能使用实际类,控制器具有该类的实例;基本上与上面完全相同的代码 - 请参阅current_user,但您只需要一次传递控制器实例,而不是每次调用方法

module Auth
  # this method is 'mixed' into controller (self)
  def initialize_authorizer
    @authorizer = ::Auth::Authorizer(self)
  end

  # this class doesn't need to be in this namespace (module), put it where ever makes sense
  class Authorizer
    def initialize(controller)
      @controller = controller
    end

    attr_reader :controller

    def sign_in(user)
      #some stuff
      controller.session[:user_id] = user.id
    end

    def current_user
      User.find(controller.session[:user_id])
    end        
  end
end

ApplicationController < ActionController::Base
  include Auth

  before_filter :initialize_authorizer
end

def sign_user_in
  # Some stuff
  @authorizer.sign_in(@user)
end