Rails 7,多对多关系,创建动作时插入重复值collection_select

Rails 7, many to many relationship, create action inserts duplicate values when using collection_select

提问人:Anders 提问时间:11/28/2022 最后编辑:Anders 更新时间:12/10/2022 访问量:196

问:

我正在开发一个 Rails 7 应用程序。我有一个创建表单,每个公司可以有多个。我在模板中使用,让用户选择一个或多个垂直领域。出于某种原因,创建操作会尝试添加选定的垂直方向两次。我添加了一个验证,使这成为不可能。companiesverticalsform.collection_select

我的人际关系如下所示:

class Company < ApplicationRecord
  has_many :company_verticals, dependent: :destroy
  has_many :verticals, through: :company_verticals
class Vertical < ApplicationRecord
  has_many :company_verticals
  has_many :companies, through: :company_verticals
class CompanyVertical < ApplicationRecord
  belongs_to :company
  belongs_to :vertical

  validates_uniqueness_of :vertical_id, scope: :company_id // causes rollback

我的公司控制器的相关部分如下所示:

 # POST /companies or /companies.json
 def create
   @company = Company.new(company_params)
   respond_to do |format|
     if @company.save
       # never reaches here since validation kicks in

def company_params
  params.require(:company).permit(<...>, vertical_ids: [])
end

我的表格是这样的

<%= form_with(model: @company, url: [@user, @company]) do |form| %>

  ...
   <%= form.collection_select :vertical_ids, Vertical.all, :id, :name, { label: "Label" }, { multiple: true, class: input_classes } %>

提交表单时,我在终端中得到以下输出:

↳ app/controllers/companies_controller.rb:30:in 块在创建' 公司垂直创建 (2.0ms) 插入 “company_verticals” (“company_id”, “vertical_id”, “created_at”, “updated_at”) 值($1、$2、$3、$4) 返回 “id” [[“company_id”, 16], [“vertical_id”, 2], [“created_at”, “2022-11-27 20:16:57.465067”], [“updated_at”, “2022-11-27 20:16:57.465067”]] ↳ app/controllers/companies_controller.rb:30:in 块在创建' 公司垂直存在吗?(0.3ms) 从“company_verticals”(其中“company_verticals”)中选择 1 作为 1。vertical_id“ = $1 和 ”company_verticals”。company_id“ = $2 LIMIT $3 [[”vertical_id“, 2], [”company_id“, 16], [”LIMIT“, 1]] ↳ app/controllers/companies_controller.rb:30:in 'block in create' 事务 (0.7ms) 回滚block in create' CompanyVertical Exists? (0.5ms) SELECT 1 AS one FROM "company_verticals" WHERE "company_verticals"."vertical_id" = $1 AND "company_verticals"."company_id" = $2 LIMIT $3 [["vertical_id", 2], ["company_id", 16], ["LIMIT", 1]] ↳ app/controllers/companies_controller.rb:30:in block in create' CompanyVertical Exists? (4.5ms) SELECT 1 AS one FROM "company_verticals" WHERE "company_verticals"."vertical_id" = $1 AND "company_verticals"."id" != $2 AND "company_verticals"."company_id" = $3 LIMIT $4 [["vertical_id", 2], ["id", 52], ["company_id", 16], ["LIMIT", 1]] ↳ app/controllers/companies_controller.rb:30:in

如果我删除验证 (),它不会验证,但公司最终会得到重复的垂直行业。validates_uniqueness_of :vertical_id, scope: :company_id

知道为什么会这样吗?

我在更新方法中使用了相同的 html 模板,但它工作正常。

更新

传递给控制器的参数:

  Parameters: {"authenticity_token"=>"[FILTERED]", "company"=>{"name"=>"Test", "registration_number"=>"12345", "vat_identification_number"=>"12345", "url_name"=>"test", "bio"=>"", "vertical_ids"=>["", "1", "2", "3"], "contact_information_attributes"=>{"email"=>"", "phone_number"=>""}, "user_id"=>"1", "address_attributes"=>{"country_id"=>"1", "street_address"=>"Test", "city"=>"test", "zip_code"=>"test"}}, "commit"=>"Skapa företag", "user_id"=>"1"}

生成的 HTML:

<input name="company[vertical_ids][]" type="hidden" value="" autocomplete="off">

<select multiple="multiple" name="company[vertical_ids][]" id="company_vertical_ids">
  <option selected="selected" value="1">Vert 1</option>
  <option selected="selected" value="2">Vert 2</option>
  <option selected="selected" value="3">Vert 3</option>
  <option value="4">Vert 4</option>
</select>
Ruby-on-Rails Ruby 对多 集合选择

评论

2赞 Beartech 11/28/2022
您可以在实际提交之前添加 Web 控制台吗?显示参数被传递给控制器的部分?此外,表单相关部分的实际生成的 HTML 可能会有所帮助。
0赞 Anders 12/1/2022
@Beartech 我已经更新了我的问题以包含参数并生成了 HTML。
0赞 Beartech 12/1/2022
来自集合选择上方的隐藏输入来自哪里?
1赞 kevinluo201 12/4/2022
你能检查和的值,然后运行然后检查吗?因为我没有这个问题。@companycompany_params@company.valid?@company.errors@company = Company.new(company_params)
1赞 Cristian Bica 12/7/2022
您发布的代码中缺少某些内容。使用您在上面发布的参数,请求将成功。我用你的示例 gist.github.com/cristianbica/489ebafb0e5c69e78984f8e7f083b982 创建了一个文件,它通过了。请求失败的唯一方式是某个垂直 ID 被传递两次(在您发布的日志中,您可以看到它检查vertical_id 2 是否存在,它会添加它,然后再次检查)。你能用我发布的单文件 rails 应用程序复制这个问题吗?

答: 暂无答案