创建销售后,将为现有的每个产品创建单独的SaleItem。 SaleItem是唯一引用销售或产品的模型。
我希望能够直接从每个Sale#show中查看和更新SaleItem discount_percentage(decimal)和include_in_sale(boolean)属性。
我认为最好将表单指向POST到SaleItem #index而不是编辑,所以我不必担心:id并且可以在完成所有更新后重定向页面。
中获取了form_tag结构的基本概念非常感谢任何使用最少数量的数据库来实现此功能的帮助!
修改1:更新了强参数以允许未允许的参数。
服务器日志显示以下内容导致回滚:
未经许可的参数:: 0,:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13 ,:14,:15,:16,:17,:18,:19,:20,:21,:22,:23,:24,:25,:26,:27,:28,:29,: 30,:31
参数值也是字符串而不是整数。见link.
出售的
has_many :sale_items
has_many :products, :through => :sale_items
促销商品
belongs_to :sale, dependent: :destroy
belongs_to :product
产品
has_many :sale_items
销售
def show
@sale_items = @sale.sale_items
end
SaleItems
before_action :sale_items_batch_update, only: [:index]
include BatchUpdate
def index
# not relevant as data is viewed from sales#show
# just wanted to show method because this is where form_tag is pointing to.
@sale_items = SaleItem.all
end
private
def sale_item_params
params.require(:sale_item).permit(:product_id, :sale_id, :discount_percentage, :include_in_sale).tap do |whitelisted|
whitelisted['sale_item'] = params[:sale_item]['sale_item']
end
end
batch_update.rb
module BatchUpdate
private
def sale_items_batch_update
unless params['sale_item'].nil?
sale_items = params['sale_item']
sale_items.each do |key, value|
# not sure yet
end
end
# redirect_to #original sales/show.html.erb page
end
end
销售/ show.html.erb
<%= form_tag sale_items_path do %>
<% @sale_items.each_with_index do |item, index| %>
<%= fields_for 'sale_item[]', item, include_id: false do |field| %>
<%= field.hidden_field :id, value: item.id, name: "sale_item[#{index}][id]" %>
<%= field.hidden_field :product_id, value: item.product_id, name: "sale_item[#{index}][product_id]" %>
<%= field.hidden_field :sale_id, value: item.sale_id, name: "sale_item[#{index}][sale_id]" %>
<%= field.check_box :include_in_sale, value: item.include_in_sale, name: "sale_item[#{index}][include_in_sale]" %>
<%= field.text_field :discount_percentage, value: item.discount_percentage, name: "sale_item[#{index}][discount_percentage]" %>
<% end %>
<% end %>
<%= submit_tag 'Update All' %>
<% end %>
答案 0 :(得分:0)
所以我至少在这一点上得到了它。我将进行一些重大的重构,以便以后提高数据库效率。
batch_update.rb关注&amp; SaleItems控制器中对它的任何引用
视图/销售/显示
<%= form_tag batch_update_sale_items_path, method: :put do %>
<% @sale_items.each_with_index do |item, index| %>
<%= fields_for 'sale_item[]', item, include_id: false do |field| %>
<%= field.hidden_field :id, value: item.id, name: "sale_item[#{index}][id]" %>
<%= field.check_box :include_in_sale, value: item.include_in_sale, name: "sale_item[#{index}][include_in_sale]" %>
<%= field.text_field :discount_percentage, value: item.discount_percentage, name: "sale_item[#{index}][discount_percentage]" %>
<% end %>
<% end %>
<%= submit_tag 'Update All' %>
<% end %>
的routes.rb
put 'sales/:id/batch_update_sale_items', to: 'sale_items#batch_update_sale_items', as: 'batch_update_sale_items'
SaleItemsController
# path from Sale#show
def batch_update_sale_items
@sale = Sale.find(params[:id])
unless params['sale_item'].nil?
sale_items_to_update = make_batch_update_hash_pretty(params['sale_item'])
update_each_sale_item(sale_items_to_update)
end
redirect_to sale_path(@sale)
end
private
# takes params['sale_item'] from Sale#show and converts it into a more usable array of hashes
def make_batch_update_hash_pretty( batch_update_hash )
# convert params to hash & removes indexing keys
old_hash_array = (batch_update_hash.to_unsafe_h).values
# converts hash keys to_sym
old_hash_array = old_hash_array.map(&:symbolize_keys)
new_hash_array = []
old_hash_array.map do |hash|
hash[:id] = hash[:id].to_i
hash[:include_in_sale] = hash[:include_in_sale].to_i
hash[:discount_percentage] = hash[:discount_percentage].to_f
# pushes updated values/types to new hash
new_hash_array << hash
end
return new_hash_array
end
# this method will update a batch of sale_items if their attributes have changed
def update_each_sale_item( sale_items )
sale_items.each do |item|
@original_sale_item = SaleItem.find(item[:id])
# determine if sale_item attributes have been altered
if @original_sale_item.discount_percentage.to_f != item[:discount_percentage]
sale_item_attributes_changed = true
elsif @original_sale_item.include_in_sale != item[:include_in_sale]
sale_item_attributes_changed = true
else
sale_item_attributes_changed = false
end
# if true updates attribute
if sale_item_attributes_changed
@original_sale_item.update(include_in_sale: item[:include_in_sale], discount_percentage: item[:discount_percentage])
end
end
end