Anders
Anders

Reputation: 2941

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

I'm working on a Rails 7 app. I have a form for creating companies, each company can have multiple verticals. I'm using form.collection_select in the template to let users select one or many verticals. For some reason the create action tries to add the selected verticals twice. I've added a validation to not make that possible.

My relationships looks like this:

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

The relevant parts of my companies controller looks like this:

 # 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

And my form looks like this

<%= 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 } %>

When submitting the form I get the following output in the terminal:

↳ app/controllers/companies_controller.rb:30:in 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 Create (2.0ms) INSERT INTO "company_verticals" ("company_id", "vertical_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "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 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 block in create' CompanyVertical Exists? (0.3ms) 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' TRANSACTION (0.7ms) ROLLBACK

If I remove the validation (validates_uniqueness_of :vertical_id, scope: :company_id) it won't validate but the company will end up with duplicate verticals.

Any idea why this happens?

I'm using the same html template in my update method, but there it works fine.

Update

Params that gets passed to controller:

  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"}

Generated 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>

Upvotes: 1

Views: 218

Answers (0)

Related Questions