Search code examples
javascriptjqueryruby-on-railsajaxruby-on-rails-5

Pass local variable to create.js.erb for an iteration in an iteration


I have a Post and a Comment model, while a post can have multiple comments and a comment belongs to a post (and a user).

I am iterating through all Posts by doing @posts.each do |d|, which is not a big deal. Also i am iterating through all the comments of a Post by d.comments.each do |comment|. No big deal too.

Ive setted up a create.js.erb to make my app a bit more dynamic and to instantly display the comment you created under a post. While my form is working fine, i have troubles setting up the create.js.erb which is giving me a NameError - undefined local variable or method 'comment' for #<Class:> Did you mean? @comment: when submitting the forms content. After reloading the page the comment is added up, but i would like to have an instant update like a single page app would behave. i have never worked with ajax before.

I would be able to solve the whole situation if i would just display the comments on a separate posts#show view but since i am iterating through every post on the index page and want to display every comment of every post and also update the comments async i just cant figure out how to do that.

How do I create the desired behavior?

Sorry if my question is asked kinda wonky.

comments_controller.rb

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

    respond_to do |format|
      if @comment.save
        format.js {}
        format.html { redirect_to root_path, notice: 'Comment added' }
        format.json { render :show, status: :created, location: @comment }
      else
        format.html { redirect_to root_path }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

posts/index.html.erb

<% @posts.each do |d| %>
  <%= d.content %>

  <div class="comment-list">
    <%= render partial: "comments/comment", collection: d.comments %>
  </div>
<% end %>

comments/_comment.html.erb

<%# d.comments.reverse.each do |comment| %>
  <%= comment.content %>
<%# end %>

create.js.erb

$(".comment-list").append("<%= j render partial: "comments/comment" %>");

Solution

  • $(".comment-list").append("<%= j render partial: "comments/comment" %>");
    

    Replace above code with

    $(".comment-list").append("<%= j render partial: "comments/comment", locals: {comment: @comment} %>");