I have a User, Post and Like model. A user has many posts, and a user can like posts.
has_many :user_posts
has_many :users, through: :user_posts
has_many :likes
has_many :users, through: :likes
On the other side my rspecs are:
it { should have_many(:users).through(:user_posts) }
it { should have_many(:user_posts) }
it { should have_many(:likes) }
it { should have_many(:user_likes).through(:likes) }
This doesn't seem to go down very well, as rspec complains there already is a relationship through user:
Expected Post to have a has_many association called users (, Expected users to have users through likes, but got it through user_posts)
I tried all sort of combinations with class_name without much success. How should I define these relationships?
I'm making some inferences based on the code above. Let me explain the choices I made...
Your terminology around "user posts" is ambiguous to me, because it's unclear if a "user post" is something a user liked or something a user authored.
In my code, has_many :posts is referring to authorship and does not demand a join table because a post only has one author. On the other hand, has_many :liked_posts needs to go through: a join table (Likes) since it's a many-to-many relationship.
The only other thing that I've done differently is the use of the source: option in the association. Since a Like has no idea what either liked_posts or users_who_liked are, you need to tell it which of it's own associations to follow to get the records.
You can read more about Associations in the Rails API Documentation.
class User < ActiveRecord:Base
has_many :posts
has_many :likes
has_many :liked_posts, through: :likes, source: :post
end
class Like < ActiveRecord:Base
belongs_to :user
belongs_to: post
end
class Post < ActiveRecord:Base
has_many :likes
has_many :users_who_liked, through: likes, source: :user
end
Finally, as feedback on your question as-written: Tom's right in his comment above. It's not clear which classes those associations are a part of. Does a User have Users twice? Confusing. If I mis-inferred any of your business rules, let me know and I can revise my thoughts.
Related
I have two models with a relation like this:
class Ticket < ActiveRecord::Base
belongs_to :group
end
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
has_many :tickets, as: :assignable
end
class Group < ActiveRecord::Base
has_many :tickets, -> { order(:created_at) }
has_and_belongs_to_many :users
end
I need to get all tickets belonging to the same groups the user has.
How can I accomplish that? Thank you so much!
As things stand, your relations are incomplete and so Rails won't work properly. If User has_many Tickets then Tickets must belong_to (or at least has_one) User. Alternatively, User can have_many Tickets through Group, which seems more likely in this case.
However, even then, it's not clear what your Group model is doing. Particularly, it's not clear how you intend it to relate to User - this looks like quite a complex relationship.
To start with, though, try and set the models up like this:
class Ticket < ApplicationRecord
belongs_to :group
end
class Group < ApplicationRecord
belongs_to :user
has_many :tickets, dependent: :destroy
end
class User < ApplicationRecord
has_many :groups, dependent: :destroy
has_many :tickets, through: :groups
end
(You'll see that I've also inherited these models from ApplicationRecord, which is how I've always done it.)
If you set it up as above, you can get your ticket records with a simple #user.tickets.
If this works, you can then add the extra HABTM relationship for Groups and Users. But be aware that HABTM relationships can be complex and there are good and bad ways to use them.
(If the primary relationship you really want is Groups > Users > Tickets then let me know and I can adjust accordingly.)
I need your small advice help.
I have trivial models: Post and User.
A user has_many :posts and a post belongs_to :user. A post has one owner.
I need somehow add an additional relation: a post can have multiple contributors. A contributor is a user too. I need to be able to write something like this: #post.contributors (shows User records) and #user.contributed_to (shows Post records).
How do I do that?
You'll need many-to-many association here, because user has_many posts and posts has_many users.
To implement it, you need to create an additional model (for example, contribution with user_id and post_id columns)
class Contribution < ApplicationRecord
belongs_to :user
belongs_to :post
end
And your Post and User classes will contain something like this:
class Post
belongs_to :user
has_many :contributions
has_many :contributors, through: :contributions, source: :user
end
class User
has_many :posts
has_many :contributions
has_many :contributed_posts, through: :contributions, source: :post
end
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.
this seems pretty basic stuff here, but actually i'm finding it a bit harsh to define this scenario with Rails...
Perhaps any of you can provide some guidance?
So I have three Tables, Users, Invoices, and User_Invoice_Viewers (these basically map users that have viewer access to an invoice)
Now my models :
User.rb :
has_many :invoices
has_many :user_invoice_viewers
has_many :invoices, through :user_invoice_viewers
Invoice.rb
belongs_to user_invoice_viewers
belongs_to :user
User_Invoice_Viewers.rb
belongs_to :users
belongs_to :invoices
Now this just seems wrong... I repeat has_many :invoices on User model, so i expect conflict when executing : User.invoices ...
What would be the best solution for this? I had thought of putting it all on a user_invoice table, but since i expect to have more owners than viewers, for performance reasons, i decided to build a direct dependency between invoice and its owner...
Thanks
I would consider using the :class_name option on the association, so that the two relationships are named differently. Something like this:
class User < ActiveRecord::Base
has_many :invoices
has_many :user_invoice_viewers
has_many :viewable_invoices, through :user_invoice_viewers, :class_name => "Invoice"
...
end
I'm trying to figure out how to best way to create associations for the following models:
User
Category
Post
Comments
Here are the requirements I'm trying to meet:
A user can have many posts
A post belongs to a user
A post can have many comments
A comment belongs to a post
A post can belong to a category
A user does NOT have many categories.
(The number of categories is fixed and the same for all users)
A category can have many posts
In terms of routing, I'd like to be able to access a post within a certain category for a specific user. For example:
http://domain.com/users/1/categories/1/posts
Since there is no direct relationship between User and Category, I'm not quite sure how to best set up the associations. And I'm totally lost on how to configure the routes.
Here's what I have for my models:
class User < ActiveRecord::Base
has_many :posts
end
class Category < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :metric
has_many :comments
end
class Comments < ActiveRecord::Base
belongs_to :post
end
Is this a case where I should be using has_many :through relationships? Or something more complex like polymorphic associations? Thanks in advance!
Yes, it would be a very good idea to use :
User has_many :comments, :through => :posts
If you like, you can also get categories comments, by :
Category has_many :comments, :through => :posts
Remember that a through association is just a facility that allows you to do things like user.comments directly (and through is the way for the association to find the user comment that is referred to post model).