Using Rails 6. Here's what I want to achieve:
Shop has many reviews.
A review belongs to one Profile.
Profile has many reviews.
Profile can only have one review for a shop.
Profile cannot have more than one review for a shop.
Here's my association that is not working:
class Shop < ApplicationRecord
has_many :reviews, dependent: :destroy
end
class Profile < ApplicationRecord
belongs_to :user
has_many :reviews
end
class Review < ApplicationRecord
belongs_to :shop, counter_cache: true
belongs_to :profile, counter_cache: true
end
class User < ApplicationRecord
has_one :profile, dependent: :destroy
end
What is not working here is - as a current_user (with profile, hence current_user.profile), how do I get a shop's review of the current user? Technically should return one review.
class User < ApplicationRecord
has_one :profile, dependent: :destroy
has_many :reviews, through: :profile
end
current_user.reviews.find_by(shop: #shop)
Or
#shop.reviews.find_by(profile: current_user.profile)
This assumes you have actually added a compound index on reviews.shop_id and reviews.profile_id to ensure uniqueness.
Technically, in the code you showed, there is no limitation for a user (via a profile) to give multiple reviews for the same shop (which might also be correct/wanted, since over time their review could change?).
You seem to be looking for an "easy"/shorter way to retrieve the review(s) for a shop the current-user has given? However, since you need to find the reviews for a specific combination (of user and shop), you will always need to filter both on shop and profile.
Options:
current_shop.reviews.where(profile_id: current_user.profile_id)
Review.where(shop_id: current_shop.id, profile_id: current_user.profile_id)
current_user.profile.reviews.where(shop_id: current_shop.id)
These will all return an array of reviews. You could add .first or .last to make sure to get the review directly (if you are sure there is only one, or are only interested in the latest review for instance).
You could define a method on User to provide some kind of shorthand:
class User
def review_for(shop)
profile.reviews.where(shop_id: shop.id).last
end
end
which would return the last (most recent) review for that shop the user has made. And then you could just write
current_user.review_for(current_shop)
Related
I have the following schema for my Rails app :
A project has many reviews, each of those reviews is filled out by a unique User to calculate a global score.
We could say that "An Organization of Users handles many Entities that have many Projects which are reviewed by the Users".
As you can see, I have a circular reference since I linked the tables "Users" & "Reviews".
After many tries and many search, I just can't manage to associate a User to a Review...Here is what I did so far:
1. Creation of an association table "UserReviews"
2. Model User
class User < ApplicationRecord
belongs_to :organization
####
has_many :user_reviews
has_many :reviews, through: :user_reviews
end
3. Model Review
class Review < ApplicationRecord
belongs_to :project
##
belongs_to :user_reviews
has_one :user, through: :user_reviews
end
4. Model UserReview
class UserReview < ApplicationRecord
belongs_to :user
belongs_to :review
end
I want to be able to get user.reviews or review.user.
Basically...I have to admit I'm lost despite the documentation. I never had to deal with this kind of issue.
Many thanks for your help!
Why do you need UserReview model here? I suppose Review model suffices your use case.
Change the Review model to:
class Review < ApplicationRecord
belongs_to :project
belongs_to :user
end
In a playstation app I have a User model, which already has has_many through association with roles and user_roles. Now our requirement asks us to create a team model, which has one captain and that captain is a user (one record of user model) and at the same time, a team has many users as players. I implemented the scenario with the following way
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles, :dependent => :destroy
belongs_to :team
end
class Team < ApplicationRecord
has_one :captain, class_name: 'User' , foreign_key: 'captain_id'
has_many :users, dependent: :destroy
end
My problem is that I am not able to create a user without a team. When I am creating a new user it is asking team must exist. Our plan is to create a user and then we will assign each user as players and out of them, one will be a captain. So please guide me if my thought process is wrong about the use case and also suggest me the perfect association style for the use case.
Starting from Rails 5, belongs_to association validates presence by default. You can change it with optional option:
class User < ApplicationRecord
belongs_to :team, optional: true
end
I have 3 models: User, Receipt and Article.
Only association is: Receipt has_many Articles.
Now I need 4. model, which is Company. User belongs_to company, and Company has_many Users.
User needs to see only Receipts and Articles that are in his Company.
Do I need to have company_id in User, Receipts and Articles and browse by that id, or there is a better way?
User needs to see only Receipts and Articles that are in his Company
Tweak your associations like so
#app/models/user.rb
class User < ApplicationRecord
belongs_to :company
end
#app/models/company.rb
class Company < ApplicationRecord
has_many :users
has_many :receipts
has_many :articles, through: :receipts
end
#app/models/receipt.rb
class Receipt < ApplicationRecord
belongs_to :company
has_many :articles
end
#app/models/article.rb
class Article < ApplicationRecord
belongs_to :receipt
end
Now you can call #user.company.receipts and #user.company.articles
Do I need to have company_id in User, Receipts and Articles and browse
by that id
With the above approach, you need have company_id in users and receipts.
You definitely need to have company_id in User unless you are going with multitenancy. And you will also need to have company_id in Receipts but not in Article as it is already associated with the Receipt.
To access receipts you just need to do user.company.receipts
Create Relationship between two table
class Receipt < ApplicationRecord
belongs_to :company
end
class Company < ApplicationRecord
has_many :receipts
end
Get the Record in simple way using that the relationship in model
ex: user.company.receipt.first.article
I have searched and searched and found only partial solutions to my current question.
The thing is, I'd like to know if it is possible to use has_many :through along with a polymorphic association in Ruby on Rails.
I have a system where students can create travel plans (that can belong to many students) and refund claims (that can belong to only one student) for their projects. In this system, both admin users and students are able to comment on the plans and claims.
My associations are:
class Student < ActiveRecord::Base
has_and_belongs_to_many :travel_plans
has_many :refund_claims
has_many :comments, through: :travel_plans
has_many :comments, through: :refund_claims
end
class AdminUser < ActiveRecord::Base
has_many :comments
end
class TravelPlan < ActiveRecord::Base
has_and_belongs_to_many :students
has_many :comments, as: :commentable
end
class RefundClaim < ActiveRecord::Base
belongs_to :student
has_many :comments, as: :commentable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
My questions are:
Is it correct to associate comments twice in the Student model?
I don't want the AdminUsers to have travel plans and refund claims, how can I identify their comments as being made on a travel plan or on a refund claim?
Would there be a better approach?
Thanks a lot in advance for everyone!
Cheers,
You probably want to add an polymorphic author attribute to the Comment model. Than you just need has_many :comments, as: :author to the Student and AdminUser model.
If this is a new application and you are starting on the green field you might want to rethink your models a bit and add a Role and a User model. Student would than be a role of user as would AdminUser be.
Is it correct to associate comments twice in the Student model?
No, not really. If you have duplicate association name, you can only use one of them. If you want to use both, you have to name them differently.
Still a newbie here, but I still couldn't get the logic right.
Currently, I have:
User has many products.
Product has 1 user with a price attribute.
I am trying to add on:
User can offer 1 price on a product sold by another user. User can offer price on multiple products.
A Product can have many offered price by multiple users.
I have currently come out with:
class User < ActiveRecord::Base
has_many :products
has_many :offered_prices
end
class Product < ActiveRecord::Base
belongs_to :user
has_many :offered_prices
end
This is what I have done so far. It still doesn't seem quite right as I am rather confused at the same time. Your help is very much appreciated! :)
Define three models:
User | OfferedPrice | Product
The association amongst them will be:
class User < ActiveRecord::Base
has_many :products
has_many :offered_prices, through: :products
end
class OfferedPrice < ActiveRecord::Base
belongs_to :user
belongs_to :product
# To make sure a user can offer price once for against a product
validates_uniqueness_of :price, scope: [:user, :product]
end
class Product < ActiveRecord::Base
has_many :offered_prices
has_many :user, through: :offered_prices
end