I have three scaffolds
Users, Comments and Movies
In my app, I want Users to Comment on Movies
, and different users can Comment on a Movie
page.
How would i create the associations code that lets users add comments on movies and then on the movie page display all comments? COuld you please also tell me the code to count the comments, so show how many comments there are and display them in integers
What i've got so far
Comments table with Subject and Body
Movies table
Users table
user.rb
has_many: comments
movies.rb
has_many: comments
comments.rb
belongs_to :users
belongs_to :movies
Thanks !
The associations you would need is to tell what they belong to. so you would need to do the following in the models:
Comment Model:
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :movie
end
User Model:
class User < ActiveRecord::Base
has_many :comments
end
Movie Model:
class Movie < ActiveRecord::Base
has_many :comments
end
You would need to generate migrations to add the foreign key columns to the comment table. Once you have that, all you need to do is attach the comments to the movies and users through their id. Then to have them the comments display, in the view:
<% @movie.comments.each do |comment| %>
<%= comment.text %>
<% end %>
EDIT: To create a comment, you would need a link to add a new comment. in the view:
<%= link_to 'New Comment', new_movie_comment_path(@movie) %>
That should take you to the new comment view and the form for it. In the form, you can associate the comment to the user by setting a hidden field that associates the user to the comment. In the comment form view:
<%= form_for(@comment) do |f| %>
<%= f.label :user %>
<%= f.hidden_field :comment, :user_id, current_user_id %>
<% end %>
The last part assumes you have a session active.
EDIT 2:
In the routes, you would nest the comments resource inside the movies resource:
resources :movies do
resources :comments
end
EDIT 3:
In your comments controller, you'll have to point the actions to the movie. In the controller
class CommentsController < ApplicationController
before_filter :load_movie
private
def load_movie
@movie = Movie.find(params[:movie_id])
end
The private section needs to be at the bottom of the controller. With that done, update the actions to use the @movie.
def index
@comments = @movie.comments.all
end
Do that for show, new, etc actions in the controller. In the create action and update action, you'll need to update the html redirect.
format.html { redirect_to (@movie, @comment), notice: 'Comment was successfully created.' }
and
format.html { redirect_to (@movie, @comment), notice: 'Comment was successfully Updated.' }
In users.rb
has_many :movies, through: :comments
In movies.rb
has_many :users, through: comments
This is called a has-many-through association. Reference here.
To count:
number_of_comments = Comment.all.size
number_of_comments_on_a_movie = Movie.find(movie_id).comments.size
number_of_comments_by_a_user = User.find(user_id).comments.size
You may have :
class User < ActiveRecord::Base
has_many :comments, :dependent => :destroy
end
class Comment< ActiveRecord::Base
belongs_to :user
belongs_to :movie
end
class Movies< ActiveRecord::Base
has_many :comments, :dependent => :destroy
end
In yours views you can do something like :
Number of comments : <%= @movie.comments.length %>
<% @movie.comments.each do |comment| %>
Pseudo : <%= comment.user.pseudo%>
Body : <%= comment.body %>
<% end %>
If you start with Rails you should take a look at this tutorial. It's awesome for basics ;)