在Ruby on Rails中避免视图和控制器之间代码重复的最佳方法是什么?

时间:2008-12-18 08:23:29

标签: ruby-on-rails ruby model-view-controller

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

我在视图中需要相同的功能来决定是否应该在列表视图中显示管理链接,但是如何最好地避免在控制器和视图中复制代码?

我现在选择这样做的方法是拥有user_can_edit_customers?基本上是'can_edit_customers?'的包装器?在我的用户类:

的ApplicationController:

class ApplicationController 

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

这种方式所有功能都封装在用户模型中,但我仍然需要在我的控制器和助手中定义包装器,但有更聪明的方法吗?

注意,用户资料只是一个例子 - 这也适用于其他功能。

5 个答案:

答案 0 :(得分: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 :(得分:1)

更直接。控制器中的helper_method“宏”使控制器方法的行为就像它也是应用程序帮助器中的方法一样。

helper_method :current_user, :can_edit_customers?

答案 2 :(得分: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,并使您能够通过单元测试轻松覆盖您的权限。

答案 3 :(得分:0)

我认为助手是你想要的方式。至于在视图中检查用户是否具有执行某项操作的权限,您可以在会话数据中添加一个标记(例如session[:admin] = true并在您的视图中检查该内容。

答案 4 :(得分:0)

通常的做法是制作像logged_in这样的方法吗?可在控制器和视图中使用。在大多数情况下,您无需将授权逻辑下推到模型中。

绝对与用户Hates描述的方法一起使用。看看像restful_authentication和acts_as_authenticated这样的插件,看看他们是如何做到的。

有几个关于此主题的railscast(http://railscasts.com/episodes?search=authentication)。例如,您可以编写一个带有块的帮助器,然后像这样使用:

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