Categories with comments and posts - ruby-on-rails

I dont understand how to create this is relationships and routes.
I want to create comments for Category, and for Posts, It's must creating in Category#index and post#index pages.
Here is my code
category.rb
has_many :posts
has_many :comments, through: :posts
comment.rb
belongs_to :category
belongs_to :post
post.rb
belongs_to :category
has_many :comments, through: :category
My migration looks like
create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.1]
def change
create_table :posts do |t|
t.integer :category_id
t.string :name
t.string :content
t.string :file
t.timestamps
end
end
end
And i dont understand how to create routes... for showing comments on post and on categories...
Here is my route
route.rb
resources :categories do
resources :posts
How to create a good relationships, good routes? I dont understand... how to create this model to model relationships and what the fields i must create in migrations...

Do you want it so that a comment can be created either for a post or for a category? In which case, it sounds like a job for a polymorphic association (http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). Your associations would look something like this:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
class Post < ActiveRecord::Base
has_many :comments, as: :commentable
end
class Category < ActiveRecord::Base
has_many :comments, as: :commentable
end
This way a post and category can both have many comments, and a comment itself is associated with only one of them (the database columns for commentable therefore has to store not only a reference id, commentable_id, but the type of model it's referencing, commentable_type - the docs link above has more on the data migration side).
If posts are associated with categories (a category having many posts, and a post having many categories), and you want to instead show comments for a category based on the posts within a category, then your code instead would look a little like this:
class Comment < ActiveRecord::Base
belongs_to :post
end
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :categories
end
class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
has_many :comments, through: :posts
end
For this, you'll also need the database migration for a table called :categories_posts which will map posts and categories together, without the need for a model between the two. More on that at http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association.
Hope that helps!

According to your query you need to add category_id and post_id in comments table. The right way to do this by adding polymorphic association to the comments table. Go-rails posted similar tutorial on rails comments with polymorphic association

Related

How to get associated polymorphic objects in rails 5?

In my Post model, I have
has_many :followers
In my Follower model, I have
belongs_to :model
belongs_to :owner,polymorphic: true
In my User and Admin devise models, I have
has_many :followers,as: :owner
Requirement: I want to have something like Post.owners and it should return me a list of all users and/or admins that are following this post.
I'm not sure, but I think that AR doesn't provide a way to load polymorphic associations in just one query. But you can use:
post = Post.find(1)
post_followers = post.followers.includes(:owner)
post_owners = post_followers.map(&:owner)
The solution you're looking for is polymorphic has many through. You can add these lines in your model of User and Admin.
has_many :followers
has_many :posts, through: :followers, source: :owner, source_type: 'Owner'
I think you want something like this:
class Post < ApplicationRecord
belongs_to :owner, polymorphic: true
end
class User < ApplicationRecord
has_many :posts, as: :owner
end
class Follower < ApplicationRecord
has_many :posts, as: :owner
end
From an instance of your User you can then retrieve their posts with #user.posts
The same goes for your Follower, #follower.posts
If you want to get to the parent of your post instance, you can do so via #post.owner. To make this work, however, we need to set up the schema correctly by declaring both a foreign key column and a type column in the model that declares the polymorphic interface using the references form:
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :posts do |t|
# your attribs here
t.references :owner, polymorphic: true, index: true
end
end
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.

ActiveRecord, polymorphic has_many, :through, :as

I am new to Rails and I'm having a superb deal of difficulty wrapping my head around what seems to be a very simple database structure, but I'm thrown by the idea that objects must belong to other objects.
In a site that I am creating, a User may create many Posts.
A Post may fit into any number of many different Topics.
So what Rails would like is that Posts belong to both Topics and to Users, while Topics also belong to Posts (many-to-many?). This makes some sense in my head, but then I can't imagine how to create a Topic independent of a Post (which is reasonable to the site's function).
Is this possible? Any help would be greatly appreciated - this is giving me a headache!
You can use has_and_belongs_to_many (HABTM) for this kind of relationship:
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :topics
end
class Topic < ActiveRecord::Base
has_and_belongs_to_many :posts
end
in addition to the tables for users, posts and topics, you will need to create a migration for the HABTM relationship:
rails g migration create_posts_users post:references user:references
Note that the model names appear in alphabetical order in the table name
I don't think you are using polymorhpic relations here, just a regular many-to-many relation. Your model relations should look something like:
class User
has_many :posts
end
class Post
has_many :post_topics
has_many :topics, through: :post_topics
belongs_to :user
end
class Topic
has_many :post_topics
has_many :posts, through: :post_topics
end
class PostTopic
belongs_to :post
belongs_to :topic
end
This scenario is perfectly fine, a Topic can have may Posts, and a Post can have many Topics, which is a many-to-many relationship. In rails that would generally translate to has_and_belongs_to_many. Therefore you can define your models as follows:
class Post < ActiveRecord::Base
has_and_belongs_to_many :topics
end
class Topic < ActiveRecord::Base
has_and_belongs_to_many :posts
end
The corresponding generated Migration and database tables will look like this:
class CreatePotsAndTopics < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.timestamps
end
create_table :topics do |t|
t.string :name
t.timestamps
end
create_table :posts_topics, id: false do |t|
t.belongs_to :post
t.belongs_to :topic
end
end
end
As you can see both Topic and Post tables are standalone tables with no reference to any other table, which means they can be treated on their own. they way they get linked is through the posts_topics join table. Which enables you to do have access to #post.topics and #topic.posts
If you are uncomfortable with such a scenarios pick up a good rails book or do an online tutorial or course which walk you through creating a full rails application.

Nested associates the rails way

I'm fairly new to Rails and I'm trying to gain a better understanding of how to be leverage the Rails framework for my associations.
While it's not specific for my app, the structure is similar -- for my example, I'll use the standard blog associates.
Example Models:
class Author < ActiveRecord::Base
has_many :posts, :through => :posts
end
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
My challenge is that I want to select all comments that belong to a specific author. I understand how to reference post and author elements that are associated with a specific post:
comment_author = Comment.first
puts comment_author.post.author.name
But as I stated I'm trying to select all comments that belong to a specific author. I could accomplish this by doing a find_by_sql, but I want to ensure db independence and I want to do this the "Rails way."
Thanks!
You can use the has_many :through assocication:
class Author < ActiveRecord::Base
has_many :posts
has_many :comments, :through => :posts
end
#Femaref provided the exact answer to your question and you should accept it. Mine is merely a complement.
If an author can leave comments on posts, here is what you might want to do:
class Author
has_many :posts
has_many :comments
has_many :responses, through: :posts, source: :comments
end
class Post
belongs_to :author
has_many :comments
end
class Comment
belongs_to :author
belongs_to :post
end
To get all the comments left by sophia: sophia.comments
To get all the comments left on sophia's posts: sophia.responses
See the options for has_many (especially through and source)

Comment belongs_to one of several models

My scenario is that there are several different models which can have comments. Trying to figure out the relationships:
Post
has_many :comments
Update
has_many :comments
Comment
belongs_to EITHER :post OR :update (but not both)????
Whats the proper way to set up the comment relationships? I want to be able to call Post.comments and Update.comments
Smells like a polymorphic association:
With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model.
So you'd want something like this:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Post < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Update < ActiveRecord::Base
has_many :comments, :as => :commentable
end
You'd have to set up a few things in the database for this to work as well. See the Polymorphic Associations section of the Active Record Associations Guide for details on the columns you'll need.

Resources