Apane101
Apane101

Reputation: 1123

How to allow users to comment

So, I'd like users to be able to comment. At the present moment anyone can comment just by typing in a arbitrary name in the name field.

But I'd like to associate a comment with a user. So there will no longer be a need for a name field in the comments form as it will be the users name.

How can this be done?

I've followed Ryan Bates railscast but he never associates comments with users.

comments_controller.rb

class CommentsController < ApplicationController
  before_action :set_comment, only: [:show, :edit, :update, :destroy]


  def index
    @comments = Comment.where("song_id IS NOT ?", nil)
  end

  def show
  end

  # GET /comments/new
  def new
  end

  # GET /comments/1/edit
  def edit
  end

  # POST /comments
  # POST /comments.json
  def create
    @comment = Comment.new(comment_params)    

    respond_to do |format|
      if @comment.save
        format.html { redirect_to song_url(@comment.song_id), notice: 'Comment was successfully created.'  }
        format.json { render action: 'show', status: :created, location: @comment}
      else
        format.html { render action: 'new' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end


  # PATCH/PUT /comments/1
  # PATCH/PUT /comments/1.json
  def update
    respond_to do |format|
      if @comment.update(comment_params)
        format.html { redirect_to song_url(@comment.song_id), notice: 'Comment was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /comments/1
  # DELETE /comments/1.json
  def destroy
    @comment.destroy
      redirect_to song_url(@comment.song_id)
    end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_comment
      @comment = Comment.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def comment_params
      params.require(:comment).permit(:song_id, :author_name, :site_url, :content, :user_id)
    end
end

user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :songs
  has_many :comments

  acts_as_voter

end

comment.rb

class Comment < ActiveRecord::Base

  belongs_to :user
  belongs_to :song
end

comments#form.html.erb

<%= form_for @comment do |f| %>
  <% if @comment.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@comment.errors.count, "error") %> prohibited this comment from being saved:</h2>

      <ul>
      <% @comment.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>


    <div id="comment_form">
  <div class="field">
     <%= f.hidden_field :song_id %>
      <p>
        <%= f.text_field :author_name, placeholder: "Name"  %>
      </p>

      <p>
        <%= f.text_area :content, :rows => '12', :cols => 35, placeholder: "Leave a comment..."  %>
      </p>
      <p><%= f.submit "Submit" %></p>
    <% end %>
    <br /><br />

    </div></div>

Upvotes: 0

Views: 287

Answers (1)

jameswilliamiii
jameswilliamiii

Reputation: 878

Your Comment table should have a column named user_id if it does not already. Then you can assign the user_id two different ways. These assume you have a current_user method. If you do not, then you will have to fill in the user_id from whatever session store or method you are using.

You could create a hidden_field in your form to assign it.

<%= f.hidden_field :user_id, value: current_user.id %>

but as noted by @rmagnum2002 this could be a security concern due to a user could edit this.

You could assign it during the create action:

def create
  @comment = Comment.new(comment_params)
  @comment.user_id = current_user.id

  respond_to do |format|
    if @comment.save
      format.html { redirect_to song_url(@comment.song_id), notice: 'Comment was successfully created.'  }
      format.json { render action: 'show', status: :created, location: @comment}
    else
      format.html { render action: 'new' }
      format.json { render json: @comment.errors, status: :unprocessable_entity }
    end
  end
end

Assigning this in the controller create action is probably best.

Upvotes: 1

Related Questions