私は現在、ショップのバックエンドに取り組んでいます。クライアントは、フォームを 1 回送信するだけで、すべての製品のリストを表示し、すべての製品の在庫値を更新できるようにしたいと考えています。私は実用的な解決策を持っていますが、それは非常に「ハッキー」であり、多くの問題を引き起こしています。私はRuby on RailsとWeb開発全般に不慣れなので、基本的な規則のいくつかとそうでないことをまだ学んでいます。
私は自分の作業ソリューションを貼り付けてから、私が抱えている問題を説明しようとします:
class Product < ActiveRecord::Base
has_many :stocks
...
end
class Stock < ActiveRecord::Base
belongs_to :product
...
end
stock_controller.rb
class StocksController < ApplicationController
def index
@products = Product.all.includes(:stocks)
end
...
def update_current
@stock_params = params[:stock]
@stock_params.each do |stock_params|
params.permit(:current_stock, :product_id)
@stock = Stock.new(stock_params)
@stock.save
end
redirect_to stocks_path, notice: 'Stocks were successfully updated'
end
...
stocks.index.html.erb
...
<%= form_tag url_for(:action => 'update_current') do |f| %>
<% @products.each do |product| %>
<tr>
<td><%= product.product_name %></td>
<td><%= product.minimum_stock %></td>
<td><%= text_field_tag "stock[][current_stock]", product.stocks.last.current_stock %></td>
<%= hidden_field_tag "stock[][product_id]", product.stocks.last.product_id %>
</tr>
<% end %>
<%= submit_tag 'save' %>
<% end %>
...
送信ボタンを押すと、必要に応じてパラメーターが設定されます。
コンソール :
Started POST "/stocks/update_current" for 127.0.0.1 at 2013-10-24 11:54:03 +0100
Processing by StocksController#update_current as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NlabBuwI06t+YN5O6p7dm+Zg2Bwc9uXrKUdWaBqNs9w=", "stock"=>[{"current_stock"=>"1", "product_id"=>"1"}, {"current_stock"=>"2", "product_id"=>"2"}, {"current_stock"=>"3", "product_id"=>"24"}, {"current_stock"=>"4", "product_id"=>"25"}, {"current_stock"=>"5", "product_id"=>"23"}, {"current_stock"=>"6", "product_id"=>"21"}, {"current_stock"=>"7", "product_id"=>"19"}, {"current_stock"=>"8", "product_id"=>"22"}, {"current_stock"=>"9", "product_id"=>"5"}], "commit"=>"save"}
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.2ms) BEGIN
SQL (136.6ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 1], ["product_id", 1], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(24.2ms) COMMIT
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.2ms) BEGIN
SQL (0.7ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 2], ["product_id", 2], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(0.7ms) COMMIT
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 3], ["product_id", 24], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(0.6ms) COMMIT
ログからわかるように、authenticity_token、およびその他のパラメーターは許可されていません。これで、トークンと他のパラメーターの目的、わからないこと、なぜこの問題に直面しているのかがわかりました。
私の推測は、私がパラメーターを許可している方法です。ハッシュの配列を許可するように strong_params に指示する方法がわかりません: stock => [{:current_stock, :product_id},{:current_stock, :product_id}, ..., ....]. params.permit(stock: [:current_stock, :product_id])
???
この場合、単一の製品ではなく製品のコレクションを扱っているため、製品の下に在庫をネストすることは意味がありません。
理想的な世界では、すべての製品の新しい在庫値を 1 回の送信で挿入し、1 回のクエリでデータベースに保存できるようにしたいと考えています。Ajax が実行可能な解決策であるかのように感じますが、何が起こっているのかを完全に理解するまでは、これ以上混乱させたくありません。
解決策やアドバイスは大歓迎です。上記が理にかなっていることを願っています!これらのことを明確に表現するのは非常に難しい場合があります。