Rails助手方法:实例变量@与普通变量的使用疑问
关于Rails助手方法中变量使用的疑问解答
先来看你提到的Michael Hartl Rails教程里的current_user方法代码:
# Returns the user corresponding to the remember token cookie. def current_user if (user_id = session[:user_id]) @current_user ||= User.find_by(id: user_id) elsif (user_id = cookies.signed[:user_id]) user = User.find_by(id: user_id) if user && user.authenticated?(:remember, cookies[:remember_token]) log_in user @current_user = user end end end
你之前疑惑是不是必须用@current_user这类实例变量,不能用the_current_user这种局部变量?其实完全没有这个强制要求,实例变量在这里只是个便捷且实用的选择,原因主要有这几点:
- 首先,Rails里的实例变量有跨上下文共享的特性:控制器里定义的
@current_user可以直接在对应的视图模板里使用,不用额外传参,这对current_user这种需要在视图里频繁判断登录状态的场景特别方便。而且实例变量如果未定义,在视图里只会返回nil不会报错,容错性更好。 - 其次,
@current_user ||= ...这个写法是在做结果缓存:第一次调用current_user时会执行数据库查询,之后再调用就直接用缓存好的实例变量,不用重复查库,提升了效率。如果用局部变量的话,每次调用方法都会重新执行查找逻辑,除非你自己实现其他缓存方式。
举个例子,其实用局部变量也能实现同样的功能,只是效率和实用性稍差:
def current_user if (user_id = session[:user_id]) user = User.find_by(id: user_id) elsif (user_id = cookies.signed[:user_id]) user = User.find_by(id: user_id) if user && user.authenticated?(:remember, cookies[:remember_token]) log_in user end end user # 直接返回局部变量user end
这种写法每次调用current_user都会重新查询数据库,而且视图里没法直接拿到这个局部变量,得每次都调用方法,不如实例变量方便。
总结一下:
- 编写有返回值的Rails助手方法时,可以使用任意类型的变量,局部变量、实例变量甚至直接返回方法调用的结果都没问题。
- 教程里用
@current_user只是因为它符合Rails的开发习惯,兼顾了缓存和视图共享的需求,和方法名叫current_user并没有强制绑定的关系——只是同名的实例变量更容易理解而已。
内容的提问来源于stack exchange,提问作者msmith1114
相关产品推荐
相关产品推荐

