Techioz Blog

Rails link_to は、JS からレンダリングする場合にのみルート一致エラーを発生させます

概要

プレゼンテーションとコメントを受け取りました。各プレゼンテーションには多くのコメントが許可されており、それらのコメントは返信できるので…

私のプレゼンテーション ショーでは、次の方法でコメントを正常に表示しています。

  <div id= "container_comments">
    <%= render @presentation.comments.where(ancestry: nil) %>
  </div>

このようにして、すべてのコメントはこのベースの _comment.html.erb ファイルを使用してレンダリングされます。

<div class="media" id="comment_<%= comment.id %>">
      <div class="media-left">
        <img src="<%= image_path("comment.png")%>" class="media-object" style="width:45px">
      </div>
      <div class="media-body">
        <h4 class="media-heading"><%=User.find(comment.author_id).username%> <small><i>Publicado: <%=comment.created_at.strftime('%F %T') %></i></small></h4>
        <p><%=comment.body%></p>
      

        <%= link_to "Reply", new_comment_congress_category_presentation_comment_path(@congress, @category, @presentation, :parent_id => comment ), :class => "btn", :remote => true, "data-toggle" => "modal", "data-target" => "#mynewcomment"%>
      
        <% replies = Comment.where(ancestry: comment) %>
        <% if replies.any? %>
          <% replies.each do |reply| %>
            <div class="media">
              <div class="media-left">
                <img src="<%= image_path("reply.png")%>" class="media-object" style="width:45px">
              </div>
              <div class="media-body">
                <h4 class="media-heading"><%=User.find(reply.author_id).username%> <small><i>Publicado: <%=reply.created_at.strftime('%F %T') %></i></small></h4>
                <p><%=reply.body%></p>
              </div>
            </div>
          <%end%>
        <%end%>
      </div>
    </div>

ここではすべてが正常に機能し、プレゼンテーションはコメントと返信を適切に読み込みます。問題は、返信の link_to:

<%= link_to "Reply", new_comment_congress_category_presentation_comment_path(@congress, @category, @presentation, :parent_id => comment ), :class => "btn", :remote => true, "data-toggle" => "modal", "data-target" => "#mynewcomment"%>

プレゼンテーションのショー ビューから正しく読み込まれますが、JS ファイルからのレンダリングは許可されておらず、キー [:id] が欠落している「一致するルートがありません」エラーが表示されます。

これが私のjsファイルです:

$("#mynewcomment").modal('hide');
$(".comment_title").val('');
$(".comment_content").val('');
<%if @comment.parent == nil%>
  $("#container_comments").append('<%= j render @comment %>');
  $("#comment_<%= @comment.id %>").hide().fadeIn(1000);
<%else%>
   <%@parent = Comment.find(@comment.parent_id)%>
   $("#comment_<%= @parent.id %>").replaceWith('<%= j render @parent %>');
<%end%>

エラーは次のようになります。

ActionView::Template::Error (No route matches {:action=>"new_comment", :category_id=>#<...category info here...>, :congress_id=>#<...congress info here...>, :controller=>"comments", :parent_id=>#<...parent comment info here...>, :presentation_id=>#<...Presentation info here...>}, missing required keys: [:id]):
 7:             <p><%=comment.body%></p>
 8:
 9:
10:             <%= link_to "Responder", new_comment_congress_category_presentation_comment_path(@congress, @category, @presentation, :parent_id => comment), :class => "btn", :remote => true, "data-toggle" => "modal", "data-target" => "#mynewcomment", :parent_id => comment %>
11:
12:             <% replies = Comment.where(ancestry: comment) %>
13:             <% if replies.any? %>

app/views/comments/_comment.html.erb:10:in 
`_app_views_comments__comment_html_erb__456499711_134033424'
app/views/comments/create.js.erb:5:in 
`_app_views_comments_create_js_erb__184660212_140959668'

まったく同じファイルが js を介してレンダリングに失敗するのはなぜだろうかと思います。ご協力に本当に感謝しています。これが私の最初の Rails プロジェクトを完了するための唯一のステップです。またよろしくお願いします。

解決策

リンクは @congress@category@presentation 変数に依存しているため、これらの同じ変数が JS テンプレートでも使用できるようにする必要があります。

この種の間違いを犯しにくくするために、ローカル ハッシュを使用して、インスタンス変数の代わりにローカル変数を使用するようにテンプレートを変更できます。

# in _comment.html.erb
<%=
  link_to "Reply",
    new_comment_congress_category_presentation_comment_path(
      congress, category, presentation,
      parent_id: comment
    )
%>

# in show.html.erb
<%=
  render @presentation.comments.where(ancestry: nil),
    locals: { congress: @congress, category: @category, presentation: @presentation }
%>

# in whatever.js.erb
<%= j render @comment, locals: { congress: @congress, ... } %>

こうすることで、3 つの必須ローカル変数のうち 1 つでも割り当てに失敗した場合、どれが不足しているのかがエラー メッセージで明示的に通知されます。