Reputation: 2941
I'm currently working on a webshop and I'm using Rails 5. I have the following models and relationships:
# Products
class Product < ApplicationRecord
has_many :product_variants
has_many :variants, through: :product_variants
...
class Variant < ApplicationRecord
has_many :product_variants
has_many :products, through: :product_variants
...
# My join table between Product and Variant
class ProductVariant < ApplicationRecord
belongs_to :price, optional: true
belongs_to :product, optional: true
belongs_to :variant, optional: true
My ProductVariant
model have an additional attribute that I would like to be updatable, t.integer "quantity"
. I'm a bit lost when it comes to update this attribute in a form_for
.
My current solution for the form looks like this (I use HAML):
= form_for @product, html: { method: :patch } do |product_builder|
= product_builder.fields_for :product_variants, product_variant do |variant_builder|
= variant_builder.hidden_field :variant_id, value: product_variant.variant.id
= variant_builder.number_field :quantity
= variant_builder.submit
But it doesn't work properly. Feels like would have been easier if the join table had an ID column, but I guess that is redundant in the database. It currently seems to create another instance of a ProductVariant
when I click the submit button.
Any idea on what I should to to properly update my quantity
attribute in my join table?
For completion
This is what gets logged when I click submit:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"uisxjfvj9LxZVJWcDVos66tJWNfHkld5+/gdfGv1D2WZsrLJcH7KLxb5eSDAYIL23mEEho18Pv/53bSEP8cC9A==", "product"=>{"product_variants_attributes"=>{"0"=>{"variant_id"=>"1", "product_id"=>"11", "quantity"=>"20", "id"=>""}}}, "commit"=>"Update Product variant", "id"=>"11"}
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT ? [["id", 11], ["LIMIT", 1]]
Unpermitted parameter: :id
(0.1ms) begin transaction
Brand Load (0.2ms) SELECT "brands".* FROM "brands" WHERE "brands"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
Variant Load (0.2ms) SELECT "variants".* FROM "variants" WHERE "variants"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Brand Exists (0.2ms) SELECT 1 AS one FROM "brands" WHERE "brands"."name" = ? AND ("brands"."id" != ?) LIMIT ? [["name", "Fredric Malle"], ["id", 4], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "product_variants" ("variant_id", "product_id", "quantity") VALUES (?, ?, ?) [["variant_id", 1], ["product_id", 11], ["quantity", 20]]
(2.7ms) commit transaction
(0.2ms) SELECT COUNT(*) FROM "note_parts" INNER JOIN "product_note_parts" ON "note_parts"."id" = "product_note_parts"."note_part_id" WHERE "product_note_parts"."product_id" = ? [["product_id", 11]]
Redirected to http://localhost:3000/products/11/edit
Completed 302 Found in 15ms (ActiveRecord: 4.0ms)
Upvotes: 0
Views: 584
Reputation: 3308
You're doing a has_many :though
. In this case, the join table needs to have a primary key (usually :id). Otherwise you can't access the join table directly like what you want here.
On the other hand, if you don't need direct access to the join table (e.g. no extra columns there), then you can set up a has_and_belongs_to_many, with no id column for the join table.
Upvotes: 1