I'm using a number_field_tag
to allow users to indicate how many of a given item they have. For each of these items then, a new record should be created in the model. Default quantity for all item fields is 0.
I'm a bit confused on how to get the params to pass appropriately (i.e., how to write the strong parameters and the form code). The controller code that I've written presumes I'll get a hash that looks like this:
itemrecord = {
"tent" => 1
"sleeping bag" => 0
...
}
And then that way, I can make the records with the following create
code (where :item_name
is the attribute for the model Inventory
):
items_to_be_saved = []
inventory_params.each do |item, quantity|
quantity.times do
items_to_be_saved << ( :item_name => item )
end
end
Currently the view/ strong parameters code I have below is producing the following output, which is different from what I need in that :item_record
is an array of quantities without the relevant item being selected.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"m2NMruoFRr6lpsuVMK9UthlY0bsJsPmf1LWce2uKaH4=", ":itemrecord"=>["", "", "", "", "", "", "", "", "2", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""], "commit"=>"Go!", "method"=>"post"}
Form code
<%= form_tag inventories_path method: :post do %>
<div class="col-xs-12">
<p><b>Items people are asking for</b></p>
</div>
<% @wishlist.each do |category, list| %>
<div class="col-xs-2">
<div class="form-group box">
<h5> <%="#{category}"%> </h5>
<% list.each do |thing| %>
<%= number_field_tag ":itemrecord[]", "#{thing}", {:size => 1, :placeholder => '0', :min => 0} %>
<%= label_tag "#{thing}" %>
</br>
<% end %>
</div>
</div>
<% end %>
<%= submit_tag "Go!", class: "btn btn-primary btn-large btn-block" %>
</div>
<% end %>
Controller code
def inventory_params
params.require(":itemrecord")
end
EDIT! I have a solution! But the params
part of it is very hacky and needs to be updated. Here's the code that works:
View
<%= number_field_tag "#{thing}", :quantity, min: 0, placeholder: 0 %>
Controller
def create
items_to_be_saved = []
inventory_params.each do |item, quantity|
quantity = quantity.to_i
quantity.times do
items_to_be_saved << ({:signup_id => @signup_parent.id, :item_name => item })
end
end
if Inventory.create items_to_be_saved
flash[:success] = "Thanks!"
redirect_to root_path
else
render new_inventory_path
end
end
def inventory_params
params.except(:action, :controller, :method, :commit, :utf8, :authenticity_token)
end
The problem is that having params.except
defeats the purpose of a "strong" parameter. I basically need the params to be passed to be any one of a laundry list of items that is defined by the controller. Similar to the form, the controller code is
def wishlist
@wishlist = {
"Category1" => ["ItemA", "ItemB"],
"Category2" => ["ItemC", "ItemD"],
}
end
As you can see in the view, the ItemA
, ItemB
, ItemC
, ItemD
are the names of each form field generated, and the key of the params hash (with :quantity
being the value). The problem is how to permit it. The below is not working with an error: undefined method
[]' for nil:NilClasson the
permit` line
def inventory_params
@wishlist.each do |category, list|
list.each do |thing|
params.permit[thing][:quantity]
params.reject { |k, v| v == "" }
end
end
end
OK I solved it. And I realized it was really simple... this is what happens when you work too long... the brain just stops
Controller code:
def create
items_to_be_saved = []
inventory_params.each do |item, quantity|
quantity = quantity.to_i
quantity.times do
items_to_be_saved << (:item_name => item )
end
end
if Inventory.create items_to_be_saved
flash[:success] = "Thanks!"
redirect_to root_path
else
render new_inventory_path
end
end
def inventory_params
params.permit[:quantity]
params.reject { |k, v| v == "" }
end
View code:
<%= form_tag inventories_path method: :post do %>
<div class="col-xs-12">
<p><b>Items people are asking for</b></p>
</div>
<% @wishlist.each do |category, list| %>
<div class="col-xs-2">
<div class="form-group box">
<h5> <%="#{category}"%> </h5>
<% list.each do |thing| %>
<%= number_field_tag "#{thing}", :quantity, min: 0, placeholder: 0 %>
<%= label_tag "#{thing}" %>
</br>
<% end %>
</div>
</div>
<% end %>
<%= submit_tag "Go!", class: "btn btn-primary btn-large btn-block" %>
</div>
<% end %>