用于路由和视图/表单的通用解决方案/模式,具有丰富的多对多关联(Rails)

时间:2015-12-19 15:21:59

标签: ruby-on-rails rails-routing

从Rails 4开始我现在用一种常见的CRUD模式进行斗争。找到了一些资源但却得不到它。

让我们假设一个产品模型,一个供应商模型以及丰富的多对价格关联。许多供应商以不同的价格出售给定的产品。每个供应商都销售许多产品。丰富的多对多联合模型的名称是" costprices"。最终会出现以下三种模式。

模型

class Product < ActiveRecord::Base
    has_many :costprices
    has_many :suppliers, through: :costprices
end

class Supplier < ActiveRecord::Base
    has_many :costprices
    has_many :products, through: :costprices
end

class Costprice < ActiveRecord::Base
    belongs_to :product
    belongs_to :supplier
end

供应商提供数百或数千种产品。产品由一个或一些(两个,三个,四个)供应商提供。对我来说,自然的方式似乎包括一个&#34;添加供应商的成本价格&#34;某些产品形式的功能,或者像我在这里一样,到产品展示页面。这个页面看起来像这样:

产品/展示视图

<p>
  <strong>Name:</strong>
  <%= @product.name %>
</p>

<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>

<!-- List all suppiers offering this product -->
<table>
  <% @product.costprices.each do |cp| %>
    <tr>
      <td>
        <%= link_to edit_product_costprice_path(cp, @product) do %>
          EDIT
        <% end %>
      </td>
      <td>
        <%= link_to product_costprice_path(cp, @product) do %>
          SHOW
        <% end %>
      </td>
      <td><%= cp.supplier.name %></td>
      <td><%= number_to_currency(cp.price) %></td>
    </tr>
  <% end %>
</table>

<%= link_to new_product_costprice_path(@product) do %>
  NEW
<% end %>

costprices / new view(_form.html.erb)

由new和edit使用。有了新的,这仍然行不通。必须添加一些用于添加供应商ID的逻辑。这可以正常编辑并正确更新价格。

<%= form_for [@product, @costprice] do |f| %>
  <div class="field">
    <%= f.label :price %><br>
    <%= f.text_field 'price', :value => number_to_currency(@costprice.price) %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

link_to助手假定这个嵌套资源:

的routes.rb

  resources :suppliers
  resources :products do
    resources :costprices
  end

此时,一切运作良好,除了&#34; NEW&#34;行动。可以单击SHOW操作和EDIT操作。单击“新建”操作会生成&#34;未定义的方法 costprices_path &#34;错误。

错误说明

  

显示/home/ubuntu/workspace/app/views/costprices/_form.html.erb其中   第1行引出:未定义的方法`costprices_path&#39;对于#&lt;#:0x007f763dca5160&gt;

     

提取的来源(第1行):

<%= form_for [@product, @costprice] do |f| %>

我明白,这些资源不会生成方法 costprices_path 。但是他们生成了一个方法 new_product_costprice_path(product_id),并且不应该调用此方法点击新建? 顺便说一句,网址对我来说似乎没问题 / products / 1 / costprices / new

主要是我对这个错误的解释和正确的解决方案感兴趣。我用一个&#34;通用解决方案/模式&#34;来领导这篇文章。除了这个错误,我还不确定如何设计一个舒适的用户界面(表单)来处理丰富的多对多关联/嵌套表单。如果某人有解决此类模式的良好链接,请分享。

costprice_controller内的新操作

def new
  @costprice = Costprice.new
end

2 个答案:

答案 0 :(得分:1)

此错误可能是由new.html.erb或来自您的控制器的新操作引起的,请检查您是否已将costprices_path添加到新操作中的new.html.erbredirect_to @costprices

如果您不熟悉m-to-m表单,可以试用simple_form,它非常易于使用,因为它可以为您处理m-to-m,请查看从simple_form中删除f.association

答案 1 :(得分:1)

韦恩带我走向正确的方向。应该已经发布了我的所有源代码。

costprices_controller我忘了为新动作设置产品。

错误:before_action :set_product, only: [:show, :edit, :update, :destroy]

正确:before_action :set_product, only: [:new, :show, :edit, :update, :destroy]

我(Rails的新手)从这个练习中学到了什么?

不要盲目依赖“铁轨魔法”,直到你真正理解幕后的一切。这是学习rails的重要部分。希望(我仍然不是他们的)之后依靠这个“神奇”来节省大量时间一次又一次地编写样板代码行是很有趣的。

首先,我甚至不知道哪些信息对于识别问题很重要。所以我不得不编辑三到四次这篇帖子提供缺失的信息。这意味着,我对rails路由有一些误解。我假设幕后有太多的“魔力”。我认为将对网址进行分析,并以某种方式神奇地调用正确的命名路线。这只是正确的一半。 <%= form_for [@product, @costprice] do |f| %>不是真正的魔法,并且基本上负责调用正确的命名路由(它不是url)。如果未设置@product(没有人为我设置@product,我必须在控制器中执行此操作)此构造等于<%= form_for [@costprice do] |f| %>,这会导致对指定路由{{1}的无效调用},当然不存在。