我的模特:
brand.rb
has_many :products
has_many :votes
belongs_to :user
accepts_nested_attributes_for :products, :allow_destroy => true
product.rb
belongs_to :user
belongs_to :brand
vote.rb
belongs_to :brand
belongs_to :user
的routes.rb
resources :brands do
resources :products
end
我的目标:在brand/show
页面的1个表单中,对现有品牌记录创建2条记录(产品和投票)。
我的解决方案:
品牌/ show.html.erb
<% form_for([@brand, @brand.send(:product).klass.new]) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= fields_for :votes, @brand.votes.new do |builder| %>
<%= builder.label :rating %>
<%= builder.text_field :rating %>
<% end %>
<%= f.submit %>
<% end %>
products_controller.rb
def create
if Brand.exists?(:id => params[:brand_id])
@review = Review.new(review_params)
@vote = Vote.new(votes_params)
@review.user_id = @vote.user_id = current_user.id
@review.brand_id = @vote.brands_id = params[:brand_id]
if @vote.valid? && @review.valid?
@vote.save
@review.save
redirect_to brands_path
else
flash[:errors][:vote] = @vote.errors
flash[:errors][:review] = @review.errors
redirect_to brands_path
end
end
end
private
def product_params
params.require(:review).permit(:title, :price)
end
def votes_params
params.require(:votes).permit(:rating)
end
这是解决我的任务的正确方法吗?我能这样用吗?
答案 0 :(得分:1)
这就是我重构你的create方法的方法:
def create
brand = Brand.find(params[:brand_id]) # no test to know if Brand exists, if it does not it means the user gave a wrong Brand id, then a 404 error should be rendered
@product = brand.products.create(products_params.merge({user_id: current_user.id}) # we can directly create this instance
@vote = brand.votes.create(votes_params) # we can directly create this instance
# we add the errors in the flash if they exist
flash[:errors][:vote] = @vote.errors if @vote.errors.present?
flash[:errors][:product] = @product.errors if @product.errors.present?
redirect_to brands_path # since we want to redirect to brands_path if the creation succeeded or failed, we don't need to use it twice in the code
end
此外,几乎没有改进:
@brand.send(:product).klass.new
# can become
@brand.products.new # produces a initialized Product instance
fields_for :votes, @brand.votes.new
# can become
f.fields_for @brand.votes.new
# notice the usage of `f` builder to generate the fields_for
# it will nest the params in `params[:brand][:votes_attributes][0]`
# brand.rb
accepts_nested_attributes_for :products, :allow_destroy => true
# add the following:
accepts_nested_attributes_for :votes, :allow_destroy => true
你显然必须相应地更新你的强力参数,但这很容易; - )
答案 1 :(得分:0)
我改变了以下逻辑:
@review.user_id = @vote.user_id = current_user.id
@review.server_id = @vote.server_id = params[:server_id]
只需将current_user.id和params [:server_id]分别添加到product_params和votes_params。
此外,我们还没有看到使用实例变量进行投票/审核的必要性。
除此之外,保存两种型号对我来说似乎没问题。