Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 has_many :through naming issue

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.

like image 320
MattC Avatar asked Feb 06 '11 05:02

MattC


1 Answers

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.

like image 64
Michelle Tilley Avatar answered Sep 21 '22 16:09

Michelle Tilley