Additional relation between records in Rails 5.0 - ruby-on-rails

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

Related

How to get all childs active-storage attachments in rails?

let's say there are 2 models.
user model:
has_many :posts
post model:
belongs_to :user
has_many_attached :files, dependent: :destroy
what I want is simply all files of the user. something like:
has _may :post_files , through: posts, class_name: "XXX"
or any other way which can give me all the files of the user.
so I want all files of all posts which belong to the user. like user.post_files
thank you all for your answers. I found the solution.
has_many_attached :files actually sets two has_many relationships:
has_many :files_attachments and
has_many :files_blobs
So in user.rb (parent model) we can simply have:
has_many :files_attachments, through: :posts
and in this way, you can have user.files_attachments to get all files of posts for one user.
Here is how the structure should be
user.rb <-- User model
has_many :posts
post.rb <-- Post model
belongs_to :user
has_many_attached :files
this way you can do
Post.post_files
or
Post.with_attached_files.find(params[:id])
In conclusion.
The attachments belong to the Post, not to the User, so there is no need to make any call to User model
Your post model acts as an xref table between users and attached files right?
You have defined a user as having many posts and a post as having many attached files. Using has_many through: will allow a user to see all the attached files for a post
user model:
Class User < ...
has_many :posts
has_many attached_files, through: :posts
post model:
Class Post < ...
belongs_to :user
has_many_attached :files, dependent: :destroy
Class AttchedFiles < ...
belongs_to :post
This enables you to do things like
User.first.attached_files
Which will return all the attached files for the user returned by the User.first declaration
Which I believe is what you were looking for

How to create a correct association

Tell me how to build a relationship between the models as follows:
- You can have a lot of posts
- Other users can write to each other positions on the wall (as in social networks, namely, when you can itself create a record or you can create it on another user page.
You should at least try to do it yourself, but here is solution:
User model:
User (id, name)
has_many :posts
has_many :comments
has_many :commented_posts, through: :comments
Post model:
Post (id, content, user_id)
belongs_to :user
has_many :comments
Comment model:
Comment (id, content, post_id, user_id)
belongs_to :user
belongs_to :post
If you refereing to posts as medium with which user can tag other users, so that the post can appear on their walls.
You can definetly use posts to write to other people walls. Thats how any social platform works, same post can act as standalone post like a blog user is publishing for his followers or in particular community.
I a social feed like platform, tags the users on the post is the only way to push the post on wall feed of any user.
So Here we can have the following entities.
User
class User < ActiveRecord::Base
has_many :usertags
has_many :posts
end
Post
class Post < ApplicationRecord
has_many :usertags, as: :usertagable
belongs_to :user
has_many :comments ,:as => :commentable
end
Usertag
class Usertag < ApplicationRecord
belongs_to :user
belongs_to :usertagable, :polymorphic => true
end
i have build polymorphic relations for usertags as you may extend the current schema to involves comments on the posts as well like the following comment model, which can be served using polymorphic relations.
class Comment < ApplicationRecord
# all the relations for the comment
belongs_to :user
belongs_to :post
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
has_many :usertags, as: :usertagable
end
Comment in turn belong to a users/author, post to which comment is attached, comment can also be commented so it can also belong to commentable. Also comment can have user mentioned as wells like posts can.
A social feed like platform, tags the users on the post is the only way to push the post on wall feed of any user.
Now you can easily fetch all the posts belonging to particular user along with usertagged, comments, auther of comments.
post_list = Post.eager_load(:followers, :user, :communities, :usertags => :user, :comments => [:usertags => :user]).select("*").where("user.id is ?", :user_id)
Hope this helps
Thanks.

Which Association Should I Use?

My app has 5 core models. I'm trying to figure out the best way to associate the models. How many tables should I build and which kind etc?
Here are the associations I would like to include and their respective models:
User
Has many boards
Has many lists
Has many cards
Has many comments
Board
Has many users
Has many lists
Has many cards
List
Belongs to board
Has many cards
Card
Belongs to board
Belongs to list
Has many comments
Comment
Belongs to card
Belongs to user
class User < ActiveRecord::Base
has_and_belongs_to_many :boards
has_many :lists, as: listable
has_many :cards, as: cardable
has_may :comments, as: commentable
end
class Board < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :lists, as: listable
has_many :cards, as: cardable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class List < ActiveRecord::Base
belongs_to :listable, :polymorphic => true
has_many :cards, as: cardable
end
class Card < ActiveRecord::Base
belongs_to :cardable, :polymorphic => true
has_many :comments, as:commentable
end
To establish HABTM relation you have to create a table named 'users_boards'
As Board and User are having many to many relationship, there will be a new table for it, if you want HABTM you can use it.
User(id, name, other_attributes...)
Board(id, name,...)
List(id, name, user_id(fk),...)
Card(id, name, user_id(fk), list_id(fk), board_id(fk),...)
Comment(id, comment_msg, user_id(fk), card_id(fk),...)
Board_User(board_id(fk), user_if(fk)) --- M-M relation
Few attributes might change if there is a has_many through relation.
FK-- Foreign key, you can use has_many through depending on your requirements.
Using polymorphic associations has some limitations, so please do through it then decide to use a polymorphic association
http://codeblow.com/questions/pros-and-cons-for-ruby-on-rails-polymorphic-associations/

Model User has many posts and can create post

Hello i have trouble with logic. In my app users can create Posts and add them to favourites. The problem is in assiciations on Posts and Users. When User creates Post user_id is applied to posts table. How can i make associations when other user or this one add Post to favourite.
You need to create another table that will join a post and user. You can call that table favorites with 2 columns: post_id and user_id
class Favorite < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
has_many :favorites
has_many :favorite_posts, through: :favorites, source: :post
end
class Post < ActiveRecord::Base
belongs_to :user
has_many :favorites
has_many :favorited_by_users, through: :favorites, source: :user
end
You could create an new model/table for association. I would take a many to many relation for this.
Table: Bookmark
user_id | post_id
How a has many :through relationship in rails work is discriped here:
http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

has_many :through relationships explained

I'm new to Rails and have some doubts about the kind of relationship do I need to use. Here is the case.
I have two models Offer and User, a user could belong to to many offers and offers can have many user. Also the users create the offers.
I think I have to use a has_many :through ralationship. For example I've created another model "Applicant". Applicant belongs_to user and belongs_to offer. But how is the relationship from the user and offer model? For example:
User Model
has_many :offer, :through => :applicant
Offer Model
has_many :user, :through => :applicant
My doubt is because I already have this two relationship
User Model
has_many :offers, :dependent => :destroy
Offer Model
belongs_to :user
After solve this, I guest I have to save the record in the applicant model from the applicanst_controller, right?
Thanks in advance
What you have described is a many-to-many relationship using a join table. You're actually pretty close but you just need to remove the has_many :offers, :dependent => :destroy from your user model and the blongs_to :user in your offer model. It should look something like this:
class User < ActiveRecord::Base
has_many :offers, :through => :applicants
end
class Applicant < ActiveRecord::Base
belongs_to :users
belongs_to :offers
end
class Offer < ActiveRecord::Base
has_many :users, :through => :applicants
end
You don't have to worry about the dependent destroy part as associations are automatically removed as the corresponding objects are removed. With a many to many association it doesn't really matter how you go about building the relationship. Either of the following will work:
#user.offers << #offer
#offers.users << #user
If you don't need to store any information specific to your applicant join table (e.g., time stamps, descriptions) you might instead want to look at a has_and_belongs_to_many relationship. Check out choosing between has_many_through and has_and_belongs_to_many for reference.
Edit
Heres the code for a HABTM relationship:
class User < ActiveRecord::Base
has_and_belongs_to_many :offers
end
class Offer < ActiveRecord::Base
has_and_belongs_to_many :users
end

Resources