Railstutorial.org 中的 SessionsHelper:帮助程序应该是视图中不需要的代码的通用模块吗?

发布于 2024-10-27 20:37:00 字数 635 浏览 2 评论 0原文

Railstutorial.org 有一个让我觉得有点奇怪的建议。

它建议使用此代码

class ApplicationController < ActionController::Base 
  protect_from_forgery 
  include SessionsHelper 
end 

include SessionsHelper使得是的,可以从 ApplicationController 获取这些方法,但它也使它们在任何视图中都可用。我知道身份验证/授权是跨领域的,但这真的是最好的地方吗?

在我看来,这个范围可能太宽泛了。将实现例如有条件重定向的 before_filter 的代码(如railstutorial.org 示例所做的那样)放入更常见的包含视图助手的模块中似乎令人惊讶。

视图中不严格需要的功能是否可以更好地放置在 ApplicationController 或其他地方?

或者我只是想太多了?

railstutorial.org has a suggestion which strikes me as a little odd.

It suggests this code:

class ApplicationController < ActionController::Base 
  protect_from_forgery 
  include SessionsHelper 
end 

The include SessionsHelper makes the methods available from ApplicationController, yes, but it makes them available in any view, as well. I understand that authentication/authorization is cross-cutting, but is this really the best place?

That seems to me to be potentially too broad of a scope. Putting code which implements, say, a before_filter which conditionally redirects (as the railstutorial.org example does) in a module which more commonly contains view helpers seems surprising.

Would functionality not strictly needed in views be better placed in ApplicationController or elsewhere?

Or am I just thinking too much about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

許願樹丅啲祈禱 2024-11-03 20:37:00

确实,你的感觉是对的。

我会以另一种方式实现这一点:将函数 sign_incurrent_user 添加到 ApplicationController (或者如果您确实想要:在单独的模块中在 lib 中定义并包含它),然后确保 current_user 方法在视图中可用。

简而言之:

class ApplicationController

  helper_method :current_user

  def sign_in

  end

  def current_user
    @current_user ||= user_from_remember_token
  end
end

当然,如果您要在 ApplicationController 中放置大量代码,它可能会变得混乱。在这种情况下,我将创建一个文件 lib\session_management.rb:

module SessionManagement
  def self.included(base)
    base.helper_method :current_user
  end

  def sign_in
    ..
  end

  def current_user
    ..
  end
end

在你的控制器中你可以编写:

class ApplicationController
  include SessionManagement
end

Indeed, your feeling is correct.

I would implement this the other way around: add the functions sign_in and current_user to ApplicationController (or if you really want to: in a separate module defined in lib and include it), and then make sure that the current_user method is available in the view.

In short:

class ApplicationController

  helper_method :current_user

  def sign_in

  end

  def current_user
    @current_user ||= user_from_remember_token
  end
end

Of course, if you have a lot of code to place into your ApplicationController it can get messy. In that case I would create a file lib\session_management.rb:

module SessionManagement
  def self.included(base)
    base.helper_method :current_user
  end

  def sign_in
    ..
  end

  def current_user
    ..
  end
end

and inside your controller you can then just write:

class ApplicationController
  include SessionManagement
end
韶华倾负 2024-11-03 20:37:00

他们似乎利用了这样一个事实:在 Rails 中,助手只是 ruby​​ 模块。

在我看来,将控制器之间共享的行为放置在模块中是一个很好的做法。另一方面,将其放入 Helper 中可能会产生误导,我会避免这样做。将其放置在“标准”模块中。

They seem to be taking (sneaky) advantage of the fact that, in Rails, Helpers are just ruby Modules.

Placing behavior that is shared across Controllers in a Module is, in my opinion, good practice. Putting it in a Helper, on the other hand, is potentially misleading and I would avoid it. Place it in a “standard” Module.

忆离笙 2024-11-03 20:37:00

这是一个哲学问题,与质疑脚手架中提供的 REST 方法以及脚手架是否值得拥有的争论处于同一水平。您必须考虑到这样一个事实:RailsTutorial.org 中的教程书是一本入门级的 Rails 指导指南。因此,就其所服务的目的而言,我认为它完成了工作。

但是,是否有更好的地方可以放置跨控制器和视图所需的代码?是的,有。

  • 有些人可能会遵循 Michael Hartl 的 Railstutorial 形式,并将整个 SessionHelper 包含到 ApplicationController 中。
  • 其他人可能决定仅公开视图所需的基本帮助程序,即 sign_in >、sign_outcurrent_user 等。
  • 我看到有人建议将此类代码放在 /lib 目录中并在需要的地方包含它。

都是可行的选择。无论您选择哪一个,对于性能来说可能并不那么重要,因为 Ruby 必须解析您想要从中调用(或包含)类、模块或方法的文件。所发生的情况是,在类中执行任何代码之前,Ruby 会遍历整个类一次以了解其中的内容。这一切都取决于人们的需求和应用程序的设计

This is a philosophical question on the same level as the argument that questions the REST method provided in scaffolding and if A scaffold is worth having at all. You have to consider the fact that the tutorial book in RailsTutorial.org is a get-up-and-go Rails instructive guide. So for the purpose which it serves, I think it does the job.

However, is there a better place to put code needed across controllers and views? Yes, there is.

  • Some may follow Michael Hartl form Railstutorial and include the entire SessionHelper into the ApplicationController
  • Others may decide to expose only the essential helpers needed for the view i.e. sign_in, sign_out, current_user and the like.
  • I see a suggestion to put such code in the /lib directory and include it where needed.

All are viable options. Whichever you take may not matter that much in performance because Ruby would have to parse the file which you want to call (or include) a class, module or method from. What happens is, before any code is executed in a class, Ruby goes through the whole class once to know what's in it. It all depends on what one needs and the design of their app

季末如歌 2024-11-03 20:37:00

FWIW,我将当前用户存储在 User 类中:

class User < ActiveRecord::Base
  cattr_accessor :current
  ...
end

这可以在所有 3 个 MVC 层中引用;它在控制器中的设置如下(当然,在登录时也同样如此):

def set_current_user
  User.current = (session[:user_id]) ? User.find_by_id(session[:user_id]) : nil
end

除此之外,这允许我在 ActiveRecord 级别拥有捕获当前用户的审核日志(如果适用)。

FWIW, I store the current user in the User class:

class User < ActiveRecord::Base
  cattr_accessor :current
  ...
end

This can be referenced in all 3 MVC tiers; it is set in the controller like so (and likewise on login, of course):

def set_current_user
  User.current = (session[:user_id]) ? User.find_by_id(session[:user_id]) : nil
end

Among other things, this allows me to have audit logs at the ActiveRecord level that capture the current user (when applicable).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文