这已成为关于Rails如何神奇地知道如何创建连接表记录而不指定它来创建这些记录的问题。
我正在构建一个电子商务解决方案,用户可以在其中购买软件包,并且在这些软件包中有许多项目。我创建了一个表单来处理包的创建,该表还允许您以相同的形式添加要放在包中的项目。
为了实现这一目标,我创建了一个package
模型,item
模型和一个加入两个模型的package_item
模型(并非每个项目都属于一个包,我希望用户能够添加未包含在包中的其他项目,所以我认为这是将两者联系起来的最佳方式。
我的思考过程是为可添加到包中的项创建复选框并将其作为数组提交,然后将items数组作为允许参数添加到包控制器中的strong参数方法中。
这是来自app / views / packages / _form.html.erb的表单:
<%= form_for(@package) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<h3>Items:</h3>
<% @items.each do |item| %>
<%= check_box_tag :item_ids, item.id, @package.package_items.include?(item), name: 'package[item_ids][]' %>
<!-- somehow, this displays the items correctly and allows me to submit them as an array -->
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
packages_controller(没有与我的问题无关的操作):
class PackagesController < ApplicationController
before_action :set_package, only: [:show, :edit, :update, :destroy]
def index
@packages = Package.all
end
def new
@package = Package.new
@items = Item.all
end
def create
@package = Package.new(package_params)
respond_to do |format|
if @package.save
# I thought the next block would be necessary, but apparently it isn't
# package_params[:item_ids].each do |item|
# @package.package_items.build(item_id: item)
# end
format.html { redirect_to @package, notice: 'package was successfully created.' }
format.json { render action: 'show', status: :created, location: @package }
else
format.html { render action: 'new' }
format.json { render json: @package.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_package
@package = Package.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def package_params
params.require(:package).permit(:name, :description, :item_ids => [])
end
end
为了处理包项的创建,在创建包之后,我遍历项目数组,为每个项目创建一个新的 @package.package_items
记录。
更新
上面代码块中注释掉的代码是我原先认为需要包含的代码,以便创建连接表记录。但是,我在运行该代码时发现我正在创建重复记录。所以我删除了那个块并且实现了Rails以某种方式直观地知道如果在参数中包含项目ID数组时继续创建package_items
记录。任何人都可以解释Rails如何知道如何做到这一点?
我也很好奇是否有更好或更有效的方法来完成我在这里所做的事情。任何意见都将不胜感激。
以下是我的模型供参考:
package.rb:
class Package < ActiveRecord::Base
has_many :items, through: :package_items
has_many :package_items
end
item.rb的:
class Item < ActiveRecord::Base
has_many :package_items
has_many :packages, through: :package_items
end
package_item.rb:
class PackageItem < ActiveRecord::Base
belongs_to :package
belongs_to :item
end
答案 0 :(得分:1)
自从这个问题以来,我一路走来。答案在package_params
内 - 我通过允许的参数发送item_ids
。我的模型has_many :items, through: :package_items
,允许我这样做并自动创建相关对象。