[英]Rails: Include module, but maintain module name?
Consider this code考虑这段代码
module Auth
def sign_in(user)
#some stuff
session[:user_id] = user.id
end
end
Now, I want to include this in my application controller.现在,我想将其包含在我的申请 controller 中。
ApplicationController < ActionController::Base
include Auth
end
This makes the sign_in
method available in all my controllers.这使得
sign_in
方法在我的所有控制器中都可用。 Now, to make it clear that this is not a controller action, I would like to maintain the name, so my controllers read现在,为了明确这不是 controller 操作,我想保留名称,所以我的控制器读取
def sign_user_in
# Some stuff
Auth.sign_in(@user)
end
This obviously does not work, because Rails will look for the class method in the Auth module.这显然是行不通的,因为 Rails 会在 Auth 模块中寻找 class 方法。 So the question is... Is it possible to include a module into the controller, preserve it's name or namespace, but still get access to the same scope as the controller?
所以问题是......是否可以将一个模块包含到 controller 中,保留它的名称或名称空间,但仍然可以访问与 controller 相同的 scope? (in this case, the session variable).
(在本例中为 session 变量)。
So far the least bad way I have come up with is stop including the module and in the ApplicationController and instead pass the application controller instance along when calling an auth method like this:到目前为止,我想出的最不坏的方法是停止在 ApplicationController 中包含模块,而是在调用这样的 auth 方法时传递应用程序 controller 实例:
def current_user(controller)
User.find(controller.session[:user_id])
end
Calling this method from a controller using using self
as an argument works.使用
self
作为参数从 controller 调用此方法有效。
Try this out?试试这个?
Uses an actual class for all the functionality and the controller has an instance of that class available;使用实际的 class 来实现所有功能,controller 有一个可用的 class 实例; basically the exact same code you have above - see
current_user
but you only need to pass the controller instance in once, not on every method call基本上与上面的代码完全相同 - 请参阅
current_user
但您只需要一次传递 controller 实例,而不是在每次方法调用时传递
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
It has been 9 years since I asked this question.我问这个问题已经 9 年了。 In the meantime I have realized that it is not a good idea to do this as it rubs against the language.
与此同时,我意识到这样做不是一个好主意,因为它会影响语言。
Constants have their own self
and when referencing a constant, you would expect any methods to be class methods.常量有自己的
self
,当引用常量时,您会期望任何方法都是 class 方法。 You would not expect them to have access to the calling object unless an a reference is explicitly passed during the method call, in which case you have a bidirectional dependency, which comes with its own set of problems.除非在方法调用期间显式传递引用,否则您不会期望它们能够访问调用 object,在这种情况下,您具有双向依赖性,这会带来一系列问题。 That would be a code smell and should be a cause for refactoring the software design.
那将是一种代码味道,应该成为重构软件设计的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.