문제

I've added ajax comments to my rails app and in the console I see that the comments are going through but rails is not displaying/rendering the comments on the page. My javascript seems to be working fine, I'm not sure where the glitch is

users/show.html.erb

<div class="comments">
  <h2>Comments</h2>
  <%= render :partial => 'comments/form', :locals => { :comment => @new_comment } %>
  <%= render :partial => 'comments/comment', :collection => @comments, :as => :comment %>
</div>

comments/_comment.html.erb

   <div class="comment"  id="comment-<%= comment.id %>">
   <hr>

    <%= link_to "×", comment_path(comment), :method => :delete, :remote => true, :confirm => "Are you sure you want to remove this comment?", :disable_with => "×", :class => 'close' %>
    <h4>
      <%= comment.user.username %>
      <small>
        <%= comment.updated_at %>
      </small>
    </h4>
  <p>
    <%= comment.body %>
  </p>
</div>

comments/_form.html.erb

<div class="comment-form">
  <%= simple_form_for comment,:url => comments_path,  :remote => true do |f| %>
    <%= f.input :body, :input_html => { :rows => "2" }, :label => false %>
    <%= f.input :commentable_id, :as => :hidden, :value => comment.commentable_id %>
    <%= f.input :commentable_type, :as => :hidden, :value => comment.commentable_type %>
    <%= f.button :submit, :class => "", :disable_with => "Submitting…" %>
  <% end %>
</div>

commentsController

def create 
  @comment_hash = params[:comment]
  @obj = @comment_hash[:commentable_type].constantize.find(@comment_hash[:commentable_id])
  # Not implemented: check to see whether the user has permission to create a comment on this object
  @comment = Comment.build_from(@obj, current_user, @comment_hash[:body])
  if @comment.save
    render :partial => "comments/comment", :locals => { :comment => @comment }, :layout => false, :status => :created
  else
    render :js => "alert('error saving comment');"
  end

 def destroy
    @comment = Comment.find(params[:id])
    if @comment.destroy
      render :json => @comment, :status => :ok
    else
      render :js => "alert('error deleting comment');"
    end
  end

comments.js.coffee

jQuery ->
  # create a comment
  $(".comment-form")
    .on "ajax:beforeSend", (evt, xhr, settings) ->
      $(this).find('textarea')
        .addClass('uneditable-input')
        .attr('disabled', 'disabled');
    .on "ajax:success", (evt, data, status, xhr) ->
      $(this).find('textarea')
        .removeClass('uneditable-input')
        .removeAttr('disabled', 'disabled')
        .val('');
      $(xhr.responseText).hide().insertAfter($(this)).show('slow')

      #delete/destroy a comment
      $(document)
    .on "ajax:beforeSend", ".comment", ->
      $(this).fadeTo('fast', 0.5)
    .on "ajax:success", ".comment", ->
      $(this).hide('fast')
    .on "ajax:error", ".comment", ->
      $(this).fadeTo('fast', 1)

usersController

def show
  @user = User.find(params[:id])

  #@user= User.find_by_username(params[:username])
  @comments = @user.comment_threads.order('created_at desc')
  @new_comment = Comment.build_from(@user, current_user, "")
end   

UPDATE

comment model

 class Comment < ActiveRecord::Base
  acts_as_nested_set :scope => [:commentable_id, :commentable_type]

  validates :body, :presence => true
  validates :user, :presence => true

  # NOTE: install the acts_as_votable plugin if you
  # want user to vote on the quality of comments.
  #acts_as_votable

  belongs_to :commentable, :polymorphic => true

  # NOTE: Comments belong to a user
  belongs_to :user

  # Helper class method that allows you to build a comment
  # by passing a commentable object, a user_id, and comment text
  # example in readme
  def self.build_from(obj, user_id, comment)
    new \
      :commentable => obj,
      :body        => comment,
      :user_id     => user_id
  end

  #helper method to check if a comment has children
  def has_children?
    self.children.any?
  end

  # Helper class method to lookup all comments assigned
  # to all commentable types for a given user.
  scope :find_comments_by_user, lambda { |user|
    where(:user_id => user.id).order('created_at DESC')
  }

  # Helper class method to look up all comments for
  # commentable class name and commentable id.
  scope :find_comments_for_commentable, lambda { |commentable_str, commentable_id|
    where(:commentable_type => commentable_str.to_s, :commentable_id => commentable_id).order('created_at DESC')
  }

  # Helper class method to look up a commentable object
  # given the commentable class name and id
  def self.find_commentable(commentable_str, commentable_id)
    commentable_str.constantize.find(commentable_id)
  end
end
도움이 되었습니까?

해결책 2

The problem was that one of my users in dev mode didn't have all the parameters(username) just email and no username was present. I fixed it by adding:

<% comment.user.username if comment.user  %> #added if comment.user to check if username present otherwise skip. It works perfectly now. Was stuck on one early user I created

다른 팁

If you're getting console JS responses, I'd say the problem will likely lie here:

comments.js.coffee

$(xhr.responseText).hide().insertAfter($(this)).show('slow') #-> are you sure this works?

$(this).append xhr.responseText #-> try this
alert xhr.responseText #-> or this

CommentsController

respond_to :js, :json, :html #-> cross channel

def create 
     @comment = Comment.new(comment_params) #-> convention over configuration
     #f your comment belongs_to :user, the `current_user` obj is not required.
     if @comment.save
         render :partial => "comments/comment", :locals => { :comment => @comment }, :layout => false, :status => :created
     else
         render :js => "alert('error saving comment');"
     end
  end

 def destroy
    @comment = Comment.find(params[:id])
    if @comment.destroy
      render :json => @comment, :status => :ok
    else
      render :js => "alert('error deleting comment');"
    end
  end

  private

  def comment_params
       params.require(:comment).permit(:title, :body, :etc)
  end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top