I have a model User that can create Posts
User
has_many :posts
Post
belongs_to :user
However, I want to also allow users to save posts as bookmarks. So I added the following:
Bookmark
belongs_to :post
belongs_to :user
User
has_many :posts
has_many :posts, :through => :bookmarks
Post
belongs_to :user
has_many :posts, :through => :bookmarks
This can't be right because it is now ambiguous when I do @user.posts . Does that refer to the posts the user wrote or the posts the user bookmarked?
How do you get around this problem?
How do you get around this problem?
By giving your associations unique names. It's not that you can't unambiguously access them, it's that your second one is destroying the first one.
Instead of calling both posts
, use bookmarked_posts
for your second association and use source:
to call posts
has_many :bookmarked_posts, through: :bookmarks, source: :post
Maybe something like this?
User
has_many :bookmarks
has_many :posts, through: :bookmarks
has_many :authored_posts, foreign_key: :author_id, class_name: 'Post'
Bookmark
belongs_to :post
belongs_to :user
Post
belongs_to :author, class_name: 'User'
has_many :bookmarks
has_many :users, through: :bookmarks
In this way, you are able to keep posts that are written by and bookmarked by a user separate. You could also set it up so that whenever an author creates a post, it can automatically get bookmarked by the user. i.e.
class PostsController < ActionController::Base
def create
@post = @user.authored_posts.build(post_params)
@user.posts << @post
if @post.valid?
# do good stuff
else
# do errors
end
end
end
There is a strong 1:N relationship between author and authored_posts. Then there is a weaker N:M relationship between Users and Posts using Bookmark as the join model. You can add authored posts to be bookmarked when they are created using the controller code above. Removing a bookmark on an authored post will simply remove it from the posts
relationship, but not the authored_posts
relationship.
You cannot define multiple relationships using the same name.
I did something similar to previous comments here but successfully used inverse_of
to differentiate users and 'post authors':
User
has_many :authored_posts, class_name: 'Post', inverse_of: 'author'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With