0

I have this scenario:

class Order < ActiveRecord::Base
  has_and_belongs_to_many :products
end

class Product < ActiveRecord::Base
  has_and_belongs_to_many :orders
end

class CreateJoinTableOrdersProducts < ActiveRecord::Migration
  def change
    create_join_table :orders, :products do |t|
      t.index [:order_id, :product_id]
      t.index [:product_id, :order_id]
      t.decimal :price, precision: 8, scale: 2
      t.integer :quantity, default: 1      
    end
  end
end

Now, I need to add some records using the command line:

This works fine:

Order.first.products << Product.first

But, I need to add some more fields, like: price, quantity...

How can I do this?

fpj
  • 315
  • 1
  • 14
Mattia M.
  • 464
  • 1
  • 4
  • 16
  • in this case you should use `has_many :through` – Vrushali Pawar Jun 08 '15 at 13:02
  • I think you are going _against_ Rails. :) Read http://stackoverflow.com/questions/2327849/add-extra-data-to-the-join-table-rails . Now if you go as the link answer is saying, you will get tools from Rails _free_. – Arup Rakshit Jun 08 '15 at 13:16

1 Answers1

2

Rails has the association.create and .build methods which allows you to create associated models on the fly:

Order.first.products.create(price: 999)

But as @test has pointed out you need to use has_many_through instead of has_and_belongs_to_many when the join table contains its own data.

has_and_belongs_to_many is used for a straight many-to-many relationship. There is no straightforward way to get the additional data such as price or quantity in a HABM relationship which is just built on a join table with the IDs of the joined models. The rails guides explain this pretty well.

class Order < ActiveRecord::Base
  has_many :row_items
  has_many :products, though: :row_items
end

class Product < ActiveRecord::Base
  has_many :row_items
  has_many :orders, though: :row_items
end

class RowItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :order
end

You would also need to create the correct table:

rails g migration CreateRowItem product:belongs_to order:belongs_to price:decimal ...

You can then create associated records via:

Order.first.row_items.create(price: 999, product: product)
max
  • 96,212
  • 14
  • 104
  • 165
  • I edited the question to include that your relationship is not defined correctly. – max Jun 08 '15 at 13:09
  • 1
    Because that's how `has_many though` works. `has_many :row_items` defines the actual relationsship. `has_many :products, though: :row_items` tells rails to go through `row_items` to find products. http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association – max Jun 08 '15 at 13:16
  • can you explain why you have used has_many :through and not has_and_belongs_to_many? – Vrushali Pawar Jun 08 '15 at 13:23
  • 1
    `has_and_belongs_to_many` is used for a straight many-to-many relationship. There is no straightforward way to get the additional data such as `price` or `quantity` in a HABM relationship which is just built on a join table with the IDs of the joined models. The rails guides explain this pretty well http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association – max Jun 08 '15 at 13:31