如何在Ruby on Rails中避免视图和控制器之间的代码重复?

3

我目前在我的ApplicationController中有一些代码,用于检查用户是否已登录并具备执行给定操作所需的访问权限(测试发生在before_filter中)。

我需要在视图中实现相同的功能,以决定是否应该在列表视图中显示管理员链接,但如何避免在控制器和视图中重复编写代码呢?

我选择的方法是将user_can_edit_customers? 本质上作为 User 类上 'can_edit_customers?' 的包装:

ApplicationController:

class ApplicationController 

然后在我的视图助手中做类似的事情。

这样所有功能都封装在 User 模型中,但我仍然需要在控制器和助手中定义包装器,但有没有更聪明的方法来处理呢?

注意,用户信息只是一个示例 - 这也适用于其他功能。

5个回答

3
我建议取消包装器,直接在传递给视图的用户对象上直接调用can_edit_customers?。如果您想要保留它们,解决方案可能是在控制器中使用helper_method
helper_method :current_user, :can_edit_customers?

def current_user
    @current_user ||= User.find_by_id(session[:user])
end

def can_edit_customers?
    @current_user.can_edit_customers?
end

这样,该方法也可以在视图中使用。

<% if can_edit_customers? -%>...<% end -%>

1

为了更直接地说,控制器中的helper_method“宏”会使控制器方法表现得像应用程序助手中的方法一样。

helper_method :current_user, :can_edit_customers?

1

个人认为你不应该使用帮助程序。

我会采取不同的解决方案。

假设我们有一个名为Cucumber的模型,某些用户不应该对其进行编辑。 我创建了#editable?方法如下:

class Cucumber < ActiveRecord::Base
  def editable?(current_user)
    # Something happens here.
  end
end

请注意,如果某个页面对所有人都可访问,则 current_user 可能为 false。
然后,在视图中,您可以执行以下操作:
<%- if @cucumber.editable?(current_user) -%>
<%# Something happens here. -%>
<%- end -%>

而在控制器中,使用一个过滤器。

这种方法最好的地方是它遵循Fat Model,并使您能够轻松地通过单元测试覆盖您的权限。


0

我认为使用帮助器是实现你想要的功能的方法。至于在视图中检查用户是否有权限执行某些操作,你可以在会话数据中设置一个标志(例如session[:admin] = true),并在视图中进行检查。


0

通常的做法是在控制器和视图中提供像logged_in?这样的方法。对于大多数情况,您不需要将授权逻辑推入模型中。

一定要采用Hates用户描述的方法。看看像restful_authentication和acts_as_authenticated这样的插件,了解它们是如何实现的。

有几个railscasts(http://railscasts.com/episodes?search=authentication)涵盖了这个主题。例如,您可以编写一个帮助程序,它接受一个块,然后像这样使用:

<%- admin_user_ do %>
  <%= link_to .. %>
  <%= link_to .. %>
  <%= link_to .. %>
<%- end %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接