Shopping cart Active Record Associations - ruby-on-rails

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: "mail#example.com", ...
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?

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

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

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

Related

How can I multiple insert the data in rails

I want to insert multiple data in rails. I'm using postgresql, the scenario is when the form submit it passes client name, email and some personal info, then also pass the desire venue with the date and also the amenities they want (ex. swimming poll, billiard poll and etc.). In my backend I will query :
venue = Venue.find(theVenue_id)
book = venue.books.new(name: client_name, email: client_email and etc)
My question is how can I insert the data in my amenity_books if the had many amenities choosen?
I trie something like this.
ex. amenities_id_choosen = [1,3]
if book.save
amenities_id_choosen.each do |x|
amenity = Amenitiy.find(x)
amenity_book = amenity.amenity_books.create(venue_id: venue.id)
end
I know this is not a good idea to insert data but that was my last choice. Does any body knows how to insert multiple data in 2 model with different data.
Models
class Amenity < ActiveRecord::Base
has_many :categorizations
has_many :venues, through: :categorizations
has_many :amenity_books
has_many :books, through: :amenity_books
end
class Venue < ActiveRecord::Base
has_many :categorizations
has_many :amenities, through: :categorizations
end
class Categorization < ActiveRecord::Base
belongs_to :venue
belongs_to :amenity
end
class Book < ActiveRecord::Base
belongs_to :venue
end
class AmenityBook < ActiveRecord::Base
belongs_to :amenity
belongs_to :venue
belongs_to :book
end
Here's an improved version:
amenities_id_choosen = [1,3]
if book.save
Amenitiy.find(amenities_id_choosen).each do |amenity|
amenity.amenity_books.create(venue_id: venue.id)
end
end
This will result in one SELECT query to find all chosen amenities and one INSERT query for each selected amenity.
Another option is to change your data model, does AmenityBook really need to have a venue? Because it looks like the venue is defined through the Book model already.
Here's a suggestion:
class Book < ActiveRecord::Base
belongs_to :venue
has_many :amenity_books
has_many :amenities, through: :amenity_books
end
class AmenityBook < ActiveRecord::Base
belongs_to :amenity
belongs_to :book
has_one :venue, through: :book
end
The code to create a booking with many amenities:
amenities_id_choosen = [1,3]
book.amenity_ids = amenities_id_choosen
if book.save
# success !
end

Rails model .build set id

In my app I have 3 model:
OrganizationType
Organization
OrganizationTypeLink
as you guess: my organization could perform more than one action, and this type of action's I want to link with organization...
And in controller I write so:
def create
#admin_organization = Organization.new(admin_organization_params)
#admin_organization.organization_type_links.build(organization_type_id: params[:organization_type_id], organization_id: #admin_organization.id)
if #admin_organization.save
....
And in model OrganizationTypeLink I see new rows in db, but how to store in Organization organization_type_link_id ? How could I store it in db?
I am new to RoR, so please give advice )
upd:
class Organization < ActiveRecord::Base
belongs_to :organization_type
has_many :organization_type_links, :dependent => :destroy
end
class OrganizationTypeLink < ActiveRecord::Base
belongs_to :organization
belongs_to :organization_type
end
class OrganizationType < ActiveRecord::Base
has_many :organizations
has_many :organization_type_links
end
how to store in Organization organization_type_link_id ? how could i store it in db?
The way you have currently defined associations in these 3 models: OrganizationType, Organization and OrganizationTypeLink
Organization has_many organization_type_links means that OrganizationTypeLink will have a foreign key named organization_id in it and not the other way round.
If you want to have organization_type_link_id in Organization then you would need to setup association as:
class Organization < ActiveRecord::Base
belongs_to :organization_type
belong_to :organization_type_link
end
class OrganizationTypeLink < ActiveRecord::Base
has_many :organizations, :dependent => :destroy
belongs_to :organization_type
end

Possible to filter an ActiveRecord query based on multiple "belongs_to" relations?

class Post < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class User < ActiveRecord::Base
has_many :posts
end
class Category < ActiveRecord::Base
has_many :posts
end
I want to get all the posts that have a relation to user AND category. Is any similar possible:
user.category.posts
Or do I need to do:
user.posts.where(category_id: category.id)
You have 1-M relationship between User and Post.
In User model association should be has_many :posts (note plural)and not has_many :post(singular).
Update your model User as below:
class User < ActiveRecord::Base
has_many :posts ## Plural posts
end
To answer below question:
get all the posts that have a relation to user AND category
Assuming that you have local variables user and category as an instance of User model and Category model respectively.
For example:
user = User.find(1); ## Get user with id 1
category = Category.find(1); ## Get category with id 1
user.posts.where(category_id: category.id) ## would get you what you need.
Also, user.category.posts will not work as User and Category models are not associated.
Try:-
user.posts.where(category_id: category.id)
Change your association like
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class User < ActiveRecord::Base
has_many :post
belongs_to :category or has_one :category
end
class Category < ActiveRecord::Base
has_one :user or belongs_to :user
has_many :posts
end
in users table add column category_id,or add column user_id in categories,because you don't have relation between those two tables.if you don't have relation you can't use association API's.then you have to use manual API to fetch the data.like how you have mentioned your question.

How to get value of some column of association table in Rails?

how can I get a weight of product through a Record model? As I know, possible to get all products of certain record but I cannot find out the way getting the weight of certain product.
class User < ActiveRecord::Base
has_many :eatings
end
class Eating < ActiveRecord::Base
belongs_to :user
has_many :records
end
class Record < ActiveRecord::Base
belongs_to :eating
end
class Product < ActiveRecord::Base
end
class WeightedProduct < ActiveRecord::Base
end
What relationships should have Record and Product models with WeightedProduct so user will be able to get weight of certain product through one line User.first.eatings.first.records.first.products.first.weight?
Looks like you're after this:
class Record < ActiveRecord::Base
belongs_to :eating
has_many :weighted_products
end
class Product < ActiveRecord::Base
has_many :weighted_products
end
class WeightedProduct < ActiveRecord::Base
belongs_to :record
belongs_to :product
end
Then User.first.eatings.first.records.first.weighted_products.first.weight
I think that should work but haven't tested.
it seems that each product has one weighted product, then in that case you should add
class Product < ActiveRecord::Base
has_one :weighted_product
end
class WeightedProduct < ActiveRecord::Base
belongs_to :product
end
and
class Record < ActiveRecord::Base
belongs_to :eating
has_many :products
end

Rails Inheritance with relationships problem

I am using single table inheritance in my project. Instead of explaining more, I'll give the code:
# person_profile.rb
class PersonProfile < ActiveRecord::Base
belongs_to :Person
end
# company_profile.rb
class CompanyProfile < ActiveRecord::Base
belongs_to :Company
end
# person.rb
class Person < User
has_one :PersonProfile
end
# company.rb
class Company < User
has_one :CompanyProfile
end
This seems to me like it should work fine. In one of my views I try if #person.PersonProfile == nil which makes perfect sense to me. But Rails doesn't like it:
Mysql::Error: Unknown column 'person_profiles.person_id' in 'where clause': SELECT * FROM `person_profiles` WHERE (`person_profiles`.person_id = 41) LIMIT 1
Rails is looking for person_id in the table person_profiles, but there is only a user_id in that table. What is the best way to fix this bug?
You can use the :foreign_key option of has_one to specify the key.
For example:
has_one :person, :foreign_key => "user_id"
See this reference.
The models specified in your model associations should be in lowercase with each word being separated by an underscore. So:
class PersonProfile < ActiveRecord::Base
belongs_to :person
end
class CompanyProfile < ActiveRecord::Base
belongs_to :company
end
class Person < User
has_one :person_profile
end
class Company < User
has_one :company_profile
end
i had to specify the foreign_key as 'user_id' because it thinks its 'person_id' by default.
class Person < User
has_one :person_profile, :foreign_key => 'user_id'
end
class Company < User
has_one :company_profile, :foreign_key => 'user_id'
end

Resources