Reputation: 2215
I am trying to implement a shopping cart within a Rails application. For this, I am trying to glue together these models:
user.rb
class User < ApplicationRecord
has_many :cart_contents
end
cart_content.rb
:
class CartContent < ApplicationRecord
belongs_to :user
has_one :product
end
product.rb
class Product < ApplicationRecord
end
To test if this arrangement is working, I tried this in the console:
irb(main):006:0> cc = CartContent.new
=>
#<CartContent:0x000055679d802a28
...
irb(main):008:0> cc.user = User.find(1)
User Load (0.2ms) SELECT "users".* FROM [...]
=> #<User id: 1, email: "[email protected]", ...
irb(main):010:0> cc.product = Product.find(1)
Product Load (0.1ms) SELECT "products".* FROM [...]
/[...]/activemodel-7.0.0/lib/active_model/attribute.rb:211:
in `with_value_from_database': can't write unknown attribute `cart_content_id` (ActiveModel::MissingAttributeError)
What am I missing here? Do I need to indicate a relationship to cart_content
in product.rb
?
Upvotes: 1
Views: 354
Reputation: 2215
I found a solution that works for me.
product.rb
class Product < ApplicationRecord
has_one :cart_content
end
cart_content.rb
class CartContent < ApplicationRecord
belongs_to :user
belongs_to :product
end
user.rb
class User < ApplicationRecord
has_many :cart_contents
has_many :products, through: :cart_contents # for convenience
end
Rails no longer expects a cart_content_id
column on Product
and the following commands all work in the console:
user = User.first
product = Product.first
cc = CartContent.new
cc.user = user
cc.product = product
cc.save
User.first.products # returns products currently in cart
Upvotes: 0
Reputation: 160
For this, you need to build relations between your models. As mentioned by Jared in this link for the foreign key to exist, you need to specify a belongs_to constraint.
The distinction is in where you place the foreign key (it goes on the table for the class declaring the belongs_to association)
class Product < ApplicationRecord
belongs_to :cart_content
end
If you also want to access all Products for User you can go for below, but you probably don't need a through
relation.
class User < ApplicationRecord
has_many :cart_contents
has_many :products, through: :cart_contents
end
Then your Product model would look like this
class Product < ApplicationRecord
belongs_to :cart_content
belongs_to :user
end
Upvotes: 0
Reputation: 17538
One possible solution: you may want your CartContent
to belongs_to :product
.
class CartContent < ApplicationRecord
belongs_to :user
has_one :product # change this to belongs_to
end
cc.product = Product.find(1)
# .. can't write unknown attribute `cart_content_id` (ActiveModel::MissingAttributeError)
has_one
will expect your products
table to have a cart_content_id
column.
See guide section 2.7 Choosing Between belongs_to and has_one
Upvotes: 2