コレクションの form_for 作成時の Rails エラー
概要
私のシステムには製品があります。また、商品には各店舗の最小/最大在庫があります。 app/views/product/edit で、それを更新する方法を作成しようとしています。 だから私はそのようなことを試しています:
<%= form_for @product.product_stores, :url => {:action => "update_stocks"} do |form| %>
<% @product.product_stores.each do |e| %>
<strong><%= e.store.name %></strong> <br/>
<%= e.id %> <br/>
<div class="row g-3 align-items-center">
<div class="col-auto">
<%= form.label :min_stock_days, class: "col-form-label" %>
</div>
<div class="col">
<%= form.text_field :min_stock_days, class: "form-control" %>
</div>
</div>
<% end %>
<% end %>
そして、画面にエラーが表示されます。
undefined method `to_key' for #<ActiveRecord::Associations::CollectionProxy
[#<ProductStore id: 913, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 24, created_at: "2024-01-17 16:14:53.475034000 -0300", updated_at: "2024-01-17 16:14:53.475034000 -0300">,
#<ProductStore id: 11617, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 1, created_at: "2024-01-17 16:58:08.503417000 -0300", updated_at: "2024-01-17 16:58:08.503417000 -0300">,
#<ProductStore id: 11618, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 2, created_at: "2024-01-17 16:58:08.506141000 -0300", updated_at: "2024-01-17 16:58:08.506141000 -0300">,
#<ProductStore id: 11619, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 3, created_at: "2024-01-17 16:58:08.508833000 -0300", updated_at: "2024-01-17 16:58:08.508833000 -0300">,
#<ProductStore id: 11620, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 4, created_at: "2024-01-17 16:58:08.511535000 -0300", updated_at: "2024-01-17 16:58:08.511535000 -0300">,
#<ProductStore id: 11621, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 5, created_at: "2024-01-17 16:58:08.514277000 -0300", updated_at: "2024-01-17 16:58:08.514277000 -0300">,
#<ProductStore id: 11622, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 6, created_at: "2024-01-17 16:58:08.516974000 -0300", updated_at: "2024-01-17 16:58:08.516974000 -0300">,
#<ProductStore id: 11623, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 7, created_at: "2024-01-17 16:58:08.519660000 -0300", updated_at: "2024-01-17 16:58:08.519660000 -0300">,
#<ProductStore id: 11624, min_stock_days: nil, max_stock_days: nil, product_id: 975, store_id: 23, created_at: "2024-01-17 16:58:08.522390000 -0300", updated_at: "2024-01-17 16:58:08.522390000 -0300">]>
Did you mean? to_set
to_ary
どうすれば修正できますか? それを実装する正しい方法は何ですか?
@Arup Rakshit に感謝します。部分的に解決しました。
私の解決策は次のとおりです。 models/product.rb に追加します
accepts_nested_attributes_for :product_stores, update_only: true
products_controller.rb に product_params を追加します
product_stores: [:min_stock_days, :max_stock_days]
そしてビュー内で次のように変更されます。
<%= form_for @product, as: :post, method: :post, :url => {:action => "update_stocks"} do |form| %>
<%= form.fields_for :product_stores, @product.product_stores.each do |ps|%>
<strong> <%= ps %> </strong>
<div class="row g-3 align-items-center">
<div class="col-auto">
<%= ps.label :min_stock_days, class: "col-form-label" %>
</div>
<div class="col">
<%= ps.text_field :min_stock_days, class: "form-control" %>
</div>
</div>
<div class="row g-3 align-items-center">
<div class="col-auto">
<%= ps.label :max_stock_days, class: "col-form-label" %>
</div>
<div class="col">
<%= ps.text_field :max_stock_days, class: "form-control" %>
</div>
</div>
<% end %>
<div>
<%= form.submit "Salvar", class: "btn btn-primary" %>
</div>
<% end %>
さて、私はまだ問題を抱えています… 各最小/最大フィールドがどのストアのものなのかわかりません。 なぜなら、私が座っている店の名前がわからないからです。
解決策
form_for ヘルパー メソッドは、コレクション用ではなく、単一のモデル インスタンス用のフォームを構築するように設計されています。
指定された実装では、ActiveRecord オブジェクトのコレクション (@product.product_stores) で form_for を使用しようとしますが、form_for は単一の ActiveRecord オブジェクトを想定しています。
これを修正するには、@product.product_stores コレクション内のアイテムごとに個別のフォームを作成する必要があります。
たとえば、各 ProductStore をループし、それぞれに個別のフォームを作成します。
<% @product.product_stores.each do |product_store| %>
<%= form_for product_store, url: {action: "update_stocks"} do |form| %>
<strong><%= product_store.store.name %></strong> <br/>
<%= product_store.id %> <br/>
<div class="row g-3 align-items-center">
<div class="col-auto">
<%= form.label :min_stock_days, class: "col-form-label" %>
</div>
<div class="col">
<%= form.text_field :min_stock_days, class: "form-control" %>
</div>
</div>
<%= form.submit %>
<% end %>
<% end %>