Rails: collect through association? - ruby-on-rails

For example, Topic has many comment, and each comment belongs to a user.
How can I get all the users have commented on the one topic, efficiently?
Now I doing this by
#commenters = #topic.comments.collect do |post|
user = post.user
user
end
And, how can I make #commenters uniq? Turn it into an array?

You could define through relation
Rails through association
Topic model
class Topic < ActiveRecord::Base
...
has_many :comments
has_many :users,
:through => :comments # add this line, it will enable association
...
end
Comment model
class Comment < ActiveRecord::Base
..
belongs_to :topic
belongs_to :user
..
end
User model
class User < ActiveRecord::Base
...
has_many :comments
...
end
then you can find users on topic.
#topic.users

Related

Rails 5: How can I see a model with via 2 models?

When I do #post = Post.first.comments.build(content: "bla", user: #user) and search via #user.comments nothing shows up. But when I do it with #post.comments, it lists the comment. How can I see my comment with both #user.comments and #post.comments?
class Post < ApplicationRecord
belongs_to :user
has_many :comments
end
my user model
class User < ApplicationRecord
has_many :posts
has_many :comments
end
comment model
class Comment < ApplicationRecord
belongs_to :user
belongs_to :post
end
use through to get comments of all posts associated with the user's posts.
class User
has_many :posts
has_many :comments, through: :posts
end

multiple belongs_to models in Rails

I have a comments model that is currently working with Articles. I would now like to have users be able to comment on the Coffeeshop reviews. Am I able to use the same comment table, or should I have a separate one (feels janky). I've not long been building with RoR (a few weeks) so still trying to get the hang of the basics.
Would I nest them in routes.rb (and how)
resources :coffeeshops do
resources :articles do
resources :comments
end
or
resources :coffeeshops do
resources :comments
end
resources :articles do
resources :comments
end
My models look like:
User
class User < ApplicationRecord
has_many :comments
end
Comments
class Comment < ApplicationRecord
belongs_to :user
belongs_to :article
belongs_to :coffeeshop
end
Articles
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
end
Coffeeshops
class Coffeeshop < ApplicationRecord
has_many :comments, dependent: :destroy
I'm then assuming I need a foreign key to tie the user and comments together, and then also the comments to the article/coffeeshop.
I'd use a polymorphic association.
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
class User < ApplicationRecord
has_many :comments
end
class Comment < ApplicationRecord
belongs_to :user
belongs_to :commentable, polymorphic: true
end
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
class Coffeeshop < ApplicationRecord
has_many :comments, as: :commentable
end
For some more information about setting up the routes/controller:
https://rubyplus.com/articles/3901-Polymorphic-Association-in-Rails-5
http://karimbutt.github.io/blog/2015/01/03/step-by-step-guide-to-polymorphic-associations-in-rails/
You can use comment model for both comments for articles and coffeeshops, but (because by default rails uses ids as primary and foreign keys I assume you use ids too) you will have to add column to comments table, where you set the comment type (You can create Enumerator in comment model, where you set 2 possible value types, each for article and coffeeshop models). If you don't add the column it will result in weird, hard to track bug where you can see comments for article on coffeeshop with same id and vise-versa.
UPD: he's little guide on using enums for rails models: http://www.justinweiss.com/articles/creating-easy-readable-attributes-with-activerecord-enums/ you will have to use it not in actual add comment form, but behind the scenes.

How to make references between two existing classes?

Rails newbie here; so I have three classes - user, article, comment - where,
class User < ActiveRecord::Base
has_many :articles
end
class Article < ActiveRecord::Base
belongs_to :user
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :article
end
Now I'm wanting the comments to be user specific i.e. each comment will be linked to a user (just how every article is linked to a user). How do I go about doing that apart from adding has_many and belongs_to in user.rb & comment.rb? I hope I made myself clear.
Add similar relations to User and Comment. So a comment will have an user_id as well as an article_id.
class User < ActiveRecord::Base
has_many :articles
has_many :comments
end
class Article < ActiveRecord::Base
belongs_to :user
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :article
belongs_to :user
end
You will have to write a migration after alerting your models to add an user_id field to your comments table.
rails g migration AddUserRefToComments user:references
Then run rake db:migrate. Hope that helps.

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.

RoR v2.3 Model associations

I was wondering how I'm suppose to associate my User, Post, and Comment models. It is suppose to be like so: The user can comment on any post and a post belongs to a user with a Boolean for being admin. I have been scratching my had for awhile trying to figure this out but nothing has made any sense at all.
Any help would be greatly appreciated.
In the most obvious arrangement Post would belong_to :user and has_many :comments, and Comment would both belong_to :user and belong_to :post. User would has_many :posts.
You can specify the following association in the model
# app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :comments
end
# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
end

Resources