使用嵌套资源干燥 Rails 视图

Posted

技术标签:

【中文标题】使用嵌套资源干燥 Rails 视图【英文标题】:DRYing up Rails Views with Nested Resources 【发布时间】:2010-03-22 21:12:17 【问题描述】:

如果您有一个既不是嵌套又嵌套的模型,例如产品,您的问题解决方案是什么:

一个“产品”可以属于_说一个“事件”,一个产品也可以是独立的。

这意味着我可以有这样的路线:

map.resources :products # /products
map.resources :events do |event|
  event.resources :products # /events/1/products
end

您如何正确处理您的观点?

注意:这是一个管理面板。我希望能够有一个“创建活动”页面,其中有一个用于创建票证(产品)、表格和检查谁是 rsvp'd 的侧面板。因此,您将单击“活动门票”侧面板按钮,它会将您带到/events/my-new-event/tickets。但管理面板还有一个根“产品”选项卡,可以列出门票和其他随机产品。 'tickets' 和 'products' 视图看起来 90% 相同,但门票将包含有关其所属活动的一些信息。

看来我必须有这样的观点:

products/index.haml products/show.haml 事件/产品/index.haml events/products/show.haml

但这似乎并不干燥。或者我可以有条件检查产品是否有事件 (@product.event.nil?),但这样视图将难以理解。

你如何处理这些情况?

非常感谢。

【问题讨论】:

【参考方案1】:

我建议您使用自己的视图制作单独的管理控制器来管理您想要的一切。并且您客户的逻辑保留在产品控制器中。

【讨论】:

【参考方案2】:

对于这个问题,我没有好的和干净的解决方案。通常,如果视图差别不大,我会使用单一视图并添加一些代码,例如@product.event.nil?。您可以随时添加一些变量或帮助程序来缩短此方法,例如 has_event? - 然后您的视图会看起来更清晰。并在这样的代码中使用它:

<% if has_event? %>
  some html
<% end %>

或单行:

<%= link_to 'Something special', foo_path if has_event? %>

另一方面,您可以为两个视图创建一些相同的部分,将它们放在某个文件夹中,例如 /shared/products/...,然后从您的视图中呈现它们,如下所示:

<%= render :partial => '/shared/products/info' %>

等等。

但如果它们没有太大区别,我真的会使用if 版本。

【讨论】:

【参考方案3】:

视图将由ProductsController 处理。您可以根据资源的嵌套更改控制器中的逻辑。

# app/controller/products_controller.rb
# ...some code...
def index
    @event = Event.find_by_id(params[:event_id]) if params[:event_id]
    @products = @event ? @event.products : Product.all
end

视图将由通常的产品视图处理

# app/views/products/index.html.haml
- unless @products.blank?
    - @products.each do |product|
        %p= product.some_attribute

【讨论】:

以上是关于使用嵌套资源干燥 Rails 视图的主要内容,如果未能解决你的问题,请参考以下文章

带有视图测试和嵌套资源的 Rspec 和 Rails

Rails 中嵌套资源视图的最佳实践?

Rails 3 link_to 路由(编辑)嵌套资源

如何更新脚手架生成的 MVC + 路由,用于在 Rails 中具有 2 个 belongs_to 关系的嵌套资源

如何在 Rails 中对常用视图代码进行分组和干燥

如何在 Rails 视图中干燥条件 content_for?