Ruby on rails 确定操作是针对成员还是针对集合
我一直在试图找到一种干净的方法来确定某个操作(在rails控制器中)是应用于成员还是应用于集合 例如,当您在routes.rb中声明Ruby on rails 确定操作是针对成员还是针对集合,ruby-on-rails,ruby,controller,Ruby On Rails,Ruby,Controller,我一直在试图找到一种干净的方法来确定某个操作(在rails控制器中)是应用于成员还是应用于集合 例如,当您在routes.rb中声明 resources :projects 您可以在“集合”上定义以下方法: 索引 创造 新的 以下是关于“成员”的定义: 更新 展示 删除 我正试图找到一种在视图中利用这种伟大模式的方法,例如: <% if @controller.action.applies_on_members? %> <%= link_to :destroy,
resources :projects
您可以在“集合”上定义以下方法:
- 索引
- 创造
- 新的
- 更新
- 展示
- 删除
<% if @controller.action.applies_on_members? %>
<%= link_to :destroy, :method => "delete", :confirm => "RU Sure" %>
<%= link_to :show, "show" %>
<% end %>
目前,我必须做以下工作:
before_filter :find_project, :except => [:new, :create, :index, :export_all, :destroy_all, :archive_all]
这很烦人,我的想法是所有这些操作都有一个共同的行为:它们是在集合上定义的
有人知道如何以干净的方式实现这一点吗
NB:我问这个问题的原因是因为我正在寻找一些在开发方面可伸缩的东西,比如before_过滤器或某些部分的行为会自动被新的自定义操作继承。
从来没有写过这样的东西
<% unless ["new", "index", "some_other_action1", "some_other_action2", "some_other_action3", "some_other_action4"].include? @controller.action_name %>
<%= link_to "Destroy", :project, :method => :delete %>
<% end %>
:删除%>
首先,对集合及其条目进行操作的模式是Rails的支柱之一。您所识别的基本上是REST所称的集合和条目。理论上,您可以对集合或集合中的条目进行应用,其中:GET;检索,放置;替换,POST;创建并删除;摧毁。虽然有点不清楚POST在一个条目上会做什么
然而,在实践中,以及在Rails中,您通常使用您已经确定的:
- 收藏
- 创建条目(POST)
- 查看条目(GET)
- 入口
- 更新条目(PUT)
- 显示条目(GET)
- 删除条目(删除)
config/initializer/rest.rb
ENTRY_ACTIONS = [:edit, :new, :show, :delete, :update]
COLLECTION_ACTIONS = [:create, :index]
然后在过滤器中使用它们,如:
before_filter :find_project, only: ENTRY_ACTIONS
要在视图中进行访问,请向应用程序助手添加一个entry\u action?
和collection\u action?
方法:
module ApplicationHelper
def entry_action?
ENTRY_ACTIONS.include?(controller.action_name.to_sym)
end
def collection_action?
COLLECTION_ACTIONS.include?(controller.action_name.to_sym)
end
end
那么在你看来,
<% if entry_action? %>
# code
<% end %>
#代码
我自己不会将其提取到常量中,而是直接编写数组,因为在我看来,当我稍后回来阅读时会更清楚。此外,大多数人在每次遇到这些方法时都必须三思而后行,而这些方法远远不是最佳的。您正在为我们解决一个在Rails中已经解决的非常常见的问题,并且几乎将其颠倒过来。您不应该在应用程序中询问控制器的状态,而应该让视图和控制器执行它需要执行的操作,尽管它知道如何执行 由于您已经确定
索引
、创建
和新建
操作适用于“集合”,并且更新
、显示
和删除
操作适用于“成员”,因此您应该定义每个相应的控制器操作和视图以使用这些形式的资源
回到您给出的示例,应该在局部中定义链接,并使用适当的视图模板渲染局部
您的before\u filter
应该写为before\u filter:find\u project,:only=>[:update,:show,:delete]
一想到应用程序中到处都能看到对
@controller.action.applications\u成员的调用?
,我就觉得你需要重新考虑你的设计。同样,您正在尝试解决Rails已经为您解决的问题。发布此问题将近一年后,我知道您已经找到了解决此问题的合理方法
如果我们看一下on=>:member
和on=>:collection
真正做了什么,基本上区别在于on=>:member
生成了一个包含:id
参数的路径,而on=>:collection
版本没有
然后,一个简单的解决方案是测试自定义方法中的params[:id]
是否为空。它看起来是这样的(比如在应用程序\u controller.rb
):
在视图中,这允许我检查以下方法:
<% if on_member? %>
<%= link_to :destroy, :method => "delete", :confirm => "RU Sure" %>
<%= link_to :show, "show" %>
<% end %>
“删除”,:确认=>“确定”%>
[问题更新]感谢您的回答。事实上,我一直在寻找一个可扩展的解决方案,这样当我添加一个新动作时,我的视图和控制器就不必在显示给用户的beforu过滤器和动作方面做太多的更改。常量解决方案不正适合这样做吗?虽然我还是会说,如果你的控制器有这么多的动作,你想做的话,这是一种代码味道。在这种情况下,在过滤之前将不同控制器中的相同数组传递给,这不会违反DRY,而是创建可读代码。这将解决(简单的)问题。
class ApplicationController < ActionController::Base
def on_member?
!params[:id].blank?
end
helper_method :on_member? #method will be accessible in views
end
before_filter :find_project, :if => :on_member?
<% if on_member? %>
<%= link_to :destroy, :method => "delete", :confirm => "RU Sure" %>
<%= link_to :show, "show" %>
<% end %>