Banner
Banner

Reputation: 603

Need clarification on has_many :through

I'm trying to create a simple version of Amazon where Users can buy and sell products. I have two types of Users: a buyer and a seller. I also have a Product model and an Order model.

I was able to create the functionality to allow a seller to create a product in order to sell it but I am having difficulty creating the associations between the buyer, order, and product. I think the closest I have gotten so far is this:

class Product < ActiveRecord::Base

  has_many :orders

  has_many :buyers, through: :orders, foreign_key: 'buyer_id'

end

class User < ActiveRecord::Base

  has_many :orders

  has_many :bought_products, through: :orders, foreign_key: 'product_id'

end

class Order < ActiveRecord::Base

  belongs_to :buyer

  belongs_to :product

end

The reason why I think this is the closest is because I am able to go to the command line and do:

p = Product.first
p.orders.build

and get back:

#<Order:0x007fc76e575728> {
            :id => nil,
       :address => nil,
      :quantity => nil,
    :created_at => nil,
    :updated_at => nil,
      :buyer_id => nil,
    :product_id => 6
}

However, I have no such luck when I'm coming from the other way:

 u = User.first

#<User:0x007fc76e53f4e8> {
                 :id => 1,
               :name => "Herbert",
              :email => "h@gmail.com",
    :password_digest => "$2a$10$FqcGq.Z3bKcK2X0gDv9VS.pzw62bcy5ouSF73f3razmhwvJVuOVj6",
         :created_at => Tue, 22 Sep 2015 16:56:33 UTC +00:00,
         :updated_at => Tue, 22 Sep 2015 17:05:43 UTC +00:00
}

u.orders.build

ActiveRecord::UnknownAttributeError: unknown attribute 'user_id' for Order.

For some reason it's trying to locate the 'user_id' but I would have thought it would be looking for the 'buyer_id' instead. I don't think I have a good understanding of the relationships I am trying to create. I would greatly appreciate it if someone could break down exactly where i'm going wrong, thanks!

Upvotes: 1

Views: 119

Answers (1)

dimakura
dimakura

Reputation: 7655

You need to fix your models:

class User < ActiveRecord::Base
  has_many :orders, class_name: 'Order', foreign_key: :buyer_id, inverse_of: :buyer
  has_many :bought_products, through: :orders, foreign_key: 'product_id', class_name: 'Product'
end

 class Order < ActiveRecord::Base
   belongs_to :buyer, class_name: 'User', inverse_of: :orders
   belongs_to :product
 end

In you case bug was produced, because Rails built Order from given User having no idea that the User is "buyer" for the Order.

Also bought_products declaration from your code needs to explicitly define class_name, while Rails can't figure out that "bought products" are simply products.

Upvotes: 2

Related Questions