19

Alright, so here's the deal. I have two tables and a join table since it's a many-to-many relationship. I have an order and an order can have many products. Obviously it goes the other way since products can be on many orders. I've got the following classes:

class Order < ActiveRecord::Base
  has_many :orders_products
  has_many :products, :through => :orders_products
end

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

class Product < ActiveRecord::Base
  has_many :orders_products
  has_many :orders, :through => :orders_products
end

I'm getting a page to display and I'm able to enter stuff and when I go to interact with the products on the saved order via @order.products I'm getting the following error:

 SQLite3::SQLException: no such table: order_products: SELECT "products".* FROM "products" INNER JOIN "order_products" ON "products".id = "order_products".product_id WHERE (("order_products".order_id = 1))

My join table is named orders_products, but as you can see it's trying to join through order_products. My limited knowledge of Rails naming conventions tells me that orders_products is the correct way to name it, and then name my model as OrderProduct. I'm really pounding my head against a wall on this one.

EDIT: I see that even though it saved my order it and I selected multiple checkboxes it did not save any values in the orders_products table, presumably for the same reason as it is erroring now.

Baylor Rae'
  • 3,995
  • 20
  • 39
MattC
  • 12,285
  • 10
  • 54
  • 78

1 Answers1

27

orders_products is not the correct naming convention for a has_many :through relationship--it is correct for a has_and_belongs_to_many relationship. In a has_many :through, the "join" model is not just for joining--it is also its own model that has its own data, that also happens to join two other models together.

If your OrderProduct model doesn't have any of it's own data, logic, or constraints, then you could use a has_and_belongs_to_many relationship instead, remove the model completely, and then your join table is named right. Otherwise, it is named according to regular model naming conventions, namely order_products.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • See the [guide for this topic](http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association) for an example of a proper `has_many :through` association. – Michelle Tilley Feb 06 '11 at 06:23
  • 3
    Ah see, I thought habtm was deprecated. – MattC Feb 06 '11 at 14:27
  • However it seems to have fixed my issue, so you get a star. Also, 5 points for an accepted answer :D – MattC Feb 06 '11 at 21:11
  • 1
    I am seeing elsewhere that if you want any constraints on the data, such as making sure each relationship is unique, you have to use a has_many :through association. So you need this even if the model doesn't have any of it's own data. I am paying the price for having read this post when deciding whether to use HABTM or has_many :through. – Carl Oct 21 '16 at 20:58
  • @unclesol updated the answer to hopefully be a bit more clear – Michelle Tilley Oct 21 '16 at 21:59