如何与多个模型共享相同的视图?

How to share same view with multiple models?

我有多个模型,它们的索引视图几乎共享完全相同的代码和布局。

.../chocolates/index.html.erb

<h1 class="col-sm-12 head">Index Bases</h1>
<hr>
<% @chocolates.each do |chocolate| %>

  <%= link_to chocolate do %>
    <%= set_img(chocolate) %>
  <% end %> 

  <ul>
    <li><%= chocolate.name %></li>
    <li><%= chocolate.position %></li>
  </ul>
  <hr>

  <div>
    <%= link_to chocolate do %>
      <span class="glyphicon glyphicon-eye-open"></span>
    <% end %> 
    <%= link_to edit_chocolate_path(chocolate) do %> 
      <span class="glyphicon glyphicon-edit"></span>
    <% end %>
    <%= link_to basis, method: :delete, data: { confirm: 'Are you sure?' } do %> 
      <span class="glyphicon glyphicon-remove"></span>
    <% end %>
  </div>

<% end %>
<hr>
<%= link_to '+ Add New Chocolate', new_chocolate_path %>

.../sweets/index.html.erb

<h1 class="col-sm-12 head">Index Bases</h1>
<hr>
<% @sweets.each do |sweet| %>

  <%= link_to sweet do %>
    <%= set_img(sweet) %>
  <% end %> 

  <ul>
    <li><%= sweet.name %></li>
    <li><%= sweet.position %></li>
  </ul>
  <hr>

  <div>
    <%= link_to sweet do %>
      <span class="glyphicon glyphicon-eye-open"></span>
    <% end %> 
    <%= link_to edit_sweet_path(sweet) do %> 
      <span class="glyphicon glyphicon-edit"></span>
    <% end %>
    <%= link_to sweet, method: :delete, data: { confirm: 'Are you sure?' } do %> 
      <span class="glyphicon glyphicon-remove"></span>
    <% end %>
  </div>

<% end %>
<hr>
<%= link_to '+ Add New Sweet', new_sweet_path %>

还有更多模型共享相同的布局,我想我一直在重复自己,所以我创建了一个共享的局部变量,以在使用该布局的每个视图中呈现。

.../sweets/index.html.erb

<% render 'shared/indexGrid', dist: @sweets%>

.../views/shared/_indexGrid.html.erb

<% title = dist.class.name.underscore.tr('_', ' ').pluralize.split.map(&:capitalize).join(' ') %>
<% sing = dist.class.name.underscore %>

<h1>Index <% title %></h1>
<hr>

<% dist.each do |sing| %>

  <%= link_to sing do %>
    <%= set_img(sing) %>
  <% end %> 

  <ul>
    <li><%= sing.name %></li>
    <li><%= sing.position %></li>
  </ul>
  <hr>

  <div>
    <%= link_to sing do %>
      <span class="glyphicon glyphicon-eye-open"></span>
    <% end %> 

    <%= link_to send("edit_#{sing.class.name.underscore}_path", sing) do %> 
      <span class="glyphicon glyphicon-edit"></span>
    <% end %>

    <%= link_to sing, class: 'square red', method: :delete, data: { confirm: 'Are you sure?' } do %> 
      <span class="glyphicon glyphicon-remove"></span>
    <% end %>
  </div>
<% end %>
<hr>
<%= link_to "+ Add New #{title}", send("new_#{sing.class.name.underscore}_path"), { class: 'btn btn-success btn-block'} %>

但它似乎没有用,因为-我认为- dist.class.name deasnt return 我期望的值但是 returns "active_record/relation"。 我在编辑视图之前尝试过相同的方法并且它适用于 dist: @sweet.

我想过使用布局,但它给我留下了与其他索引视图非常相似的大块代码。

我已经与您分享了我的尝试,问题是...

一个简单的解决方案是使用包含 class_name 作为参数的部分

 <% render 'shared/indexGrid', dist: @sweets, class_name = "Sweets"%>

或者添加一些东西让你认出哪个是来源....

你可以试试model_name

<% title = dist.model_name.to_s.underscore.tr('_', ' ').pluralize.split.map(&:capitalize).join(' ') %>

或更好

  <% title = dist.model_name.human.pluralize.titleize  %>

应该也给你想要的。

和清理路线,你可以看看PolymorphicRoutes

http://api.rubyonrails.org/classes/ActionDispatch/Routing/PolymorphicRoutes.html

所以而不是

link_to send("edit_#{sing.class.name.underscore}_path", sing)

你可以使用像

这样的东西
link_to 'Edit, edit_polymorphic_path(sing)

这应该能很好地清理您的共享索引页。

您还可以考虑创建一个 title_for(例如 )助手,returns 标题。清理它,但不是 100% 需要。

-- 第 2 部分 --

这是个好主意吗?或许?没有答案怎么办?有很多因素。所有这些模型总是完全相同的可能性有多大?以后要做出不同的作品需要付出多少努力/多少工作?如果我有一堆基本相同的模型,并且总是有完全相同的索引页,我可能会考虑做类似的事情。同样的想法用于自动生成视图等的引擎/宝石/插件。所以我想如果它们总是一样的,并且你总是希望保持它们看起来一样,那么这样的东西是非常好的。

至于 collections 在你看@sweets 之类的东西时,它不是你模型的单个实例。它可能是一个ActiveRelation。所以从 active_model 调用 model_name 不会有太大帮助。如果您查看 rails 部分指南,您将看到 render @collection。这基本上只是迭代 collection 中的每个 object,为您查看 model_name,并将其传递给相应的部分以进行渲染。

因此,如果您有一个 @sweets 的 collection,其中有一堆 Sweet object,rails 将迭代 collection。然后为您呈现 _sweet.html.erb (遵循定位哪个部分的正常规则)。有了这个,你可以将你的 <% dist.each do |sing| %> 块调整为 <%=render dist%> 然后确保每个模型都有一个部分并且它可以以不同的方式渲染它们