質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

Rails5 book_commentのcreateアクション失敗後のrenderがうまく返せません。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 218

shimoner

score 3

コメントが空の時のバリデーション時、renderして元のページに帰ろうとしているのですが、

ActionController::UrlGenerationError in BookComments#create
Showing /home/vagrant/work/Application_subject/bk2-before_debug/app/views/books/show.html.erb where line #56 raised:

No route matches {:action=>"destroy", :book_id=>"1", :controller=>"book_comments", :id=>nil}, missing required keys: [:id]
Extracted source (around line #56):
54
55
56
57
58
59

                                <td><%= book_comment.comment %></td>
                                <% if book_comment.user == current_user %>
                                    <td><%=link_to "Destroy",book_book_comment_path(@book, book_comment), method: :delete, class: "btn-sm btn-danger " %></td>
                                <% end %>

                            </tr>


commentのIDがnillですよと言われます。

もちろんcommentが空なのでrender前に

@book_comments = @book.book_comments


を代入しています。
何が原因なのか教えて頂けたらと思います。

ブックコメントコントローラー

class BookCommentsController < ApplicationController
  def create
    @book = Book.find(params[:book_id])
    @book_comment = @book.book_comments.new(book_comment_params)
    @book_comment.user_id = current_user.id
    if @book_comment.save
      flash[:success] = "Comment was successfully created."
      redirect_to request.referer
    else
      @book_new = Book.new
      @book_comments = @book.book_comments
      render '/books/show'
    end
  end

  def destroy
    @book = Book.find(params[:book_id])
    @book_comment = BookComment.find(params[:id])
    if @book_comment.user == current_user
      @book_comment.destroy
    end
    redirect_to request.referer
  end


  private
  def book_comment_params
    params.require(:book_comment).permit(:comment)
  end

end


ブックコントローラー

  before_action :ensure_correct_user, only: [:edit, :update, :destroy]

  before_action :authenticate_user!
  def show
    @book_new = Book.new
    @book = Book.find(params[:id])
    @book_comment = BookComment.new
    @book_comments = @book.book_comments
  end

  def index
    @book = Book.new
    @books = Book.all

  end

  def create
    @book = Book.new(book_params)
    @book.user_id = current_user.id
    if @book.save
      redirect_to book_path(@book), notice: "You have created book successfully."
    else
      @books = Book.all
      render 'index'
    end
  end

  def edit


  end

  def update

    if @book.update(book_params)
      redirect_to book_path(@book), notice: "You have updated book successfully."
    else
      render "edit"
    end
  end

  def destroy

    @book.destroy
    redirect_to books_path
  end

  private

  def book_params
    params.require(:book).permit(:title, :body)
  end
  def ensure_correct_user
     @book = Book.find(params[:id])
     unless @book.user == current_user
       redirect_to books_path
     end
   end


end


books_showビュー

<div class="row">
    <div class="col-xs-3">

        <h2>User info</h2>
        <%= render 'users/profile',user: @book.user %>

        <h2>New book</h2>
        <%= render 'books/newform', book: @book_new %>

    </div>

    <div class="col-xs-9">
        <h2>Book detail</h2>

        <table class="table">
                <tr>
                    <td>
                        <%= link_to user_path(@book.user) do %>
                            <%= attachment_image_tag(@book.user, :profile_image, :fill, 40, 40, fallback: "no-image-mini.jpg") %><br>
                        <%= @book.user.name %>
                        <% end %>
                    </td>
                    <td><%= link_to @book.title, book_path(@book) %></td>
                    <td><%= @book.body %></td>
                <% if @book.user == current_user %>
                    <td><%= link_to "Edit", edit_book_path(@book), class: "btn-sm btn-success edit_book_#{@book.id}" %></td>
                    <td><%= link_to "Destroy", book_path(@book), method: :delete, data: {confirm: "本当に削除してもよろしいですか?"}, class: "btn-sm btn-danger destroy_book_#{@book.id}" %></td>
                <% end %>
                    <td>
                    <% if @book.favorited_by?(current_user) %>
                        <%= link_to book_favorites_path(@book), method: :delete do %>
                            <i class="fa fa-heart" aria-hidden="true" style="color: red;"></i>
                             <%= @book.favorites.count %> いいね
                        <% end %>
                    <% else %>
                        <%= link_to book_favorites_path(@book), method: :post do %>
                            <i class="fa fa-heart-o" aria-hidden="true"></i>
                            <%= @book.favorites.count %> いいね
                        <% end %>
                    <% end %>
                    </td>
                    <td><%= @book.book_comments.count%>件コメント</td>
                </tr>
            </table>
                <div class="col-xs-12">
                    <% @book_comments.each do |book_comment| %>
                        <table style="border:none;">
                            <tr>
                                <td>
                                <%= attachment_image_tag(book_comment.user, :profile_image, :fill, 40, 40, fallback: "no-image-mini.jp") %><br>
                                <%= book_comment.user.name %>
                                <td>
                                <td><%= book_comment.comment %></td>
                                <% if book_comment.user == current_user %>
                                    <td><%=link_to "Destroy",book_book_comment_path(@book, book_comment), method: :delete, class: "btn-sm btn-danger " %></td>
                                <% end %>

                            </tr>
                        </table>
                    <% end %>
                </div>
                <div class="col-xs-6">
                 <div class="comment-form">
                    <%= form_for [@book, @book_comment] do |f| %>
                        <%= f.text_area :comment, size: "95x5" %>
                        <%= f.submit "送信", class: "btn-sm btn-primary" %>
                    <% end %>
                </div>

    </div>
</div>


ルート

Rails.application.routes.draw do
    devise_for :users, controllers: {
      sessions: 'users/sessions',
      registrations: 'users/registrations'
    }
    root 'home#top'
    get 'home/about' => 'home#about'
    resources :users,only: [:show,:index,:edit,:update]
    resources :books do
      resource :favorites, only: [:create, :destroy]
      resources :book_comments, only: [:create, :destroy]
    end

  end


ブックコメントバリデーション

class BookComment < ApplicationRecord
    belongs_to :user
    belongs_to :book
    validates :comment, presence: true
end

質問まとめ
book_commentのcreateアクションは可能です
destroyも正常に動作しているので
booksコントローラーには何も異常はないと思います。
book_commentsコントローラーの記述がおかしいのだと思いますが、
なぜこのbook_commentコントローラーの今の記述でrenderしたと時にbook_commentのidがないと言われるのがわかりません。

どうかエラーの解決にご協力くださいお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

render '/books/show' する場合、def show と同じデータが渡るようにしなければなりません。
def show では

    @book_new = Book.new
    @book = Book.find(params[:id])
    @book_comment = BookComment.new
    @book_comments = @book.book_comments


が、
def create では

    @book = Book.new(book_params)
    @book.user_id = current_user.id
      @books = Book.all


が定義されています。
viewをきちんと読んで居ないので見落としあるかもですが、以下が足りません

    @book_comment = BookComment.new
    @book_comments = @book.book_comments

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/03 22:25

    ご回答ありがとうございます。おそらく上記の説明はbooks_controllerのcreateのことを言われていると思われますが、エラーが出るのはbook_comments_controllerのcreateアクションのところでございます。

    キャンセル

  • 2020/07/04 02:20 編集

    あ、book_comments_controllerをみているつもりだったのですが違ってますね

    キャンセル

  • 2020/07/04 02:32 編集

    するとこういうことですね
    @book_comment = @book.book_comments.new(book_comment_params)
    ここで @book 割り当てられた @book_commentがsaveに失敗してidがつかないまま メモリー上の @book にぶら下がっていて、
    @book_comments = @book.book_comments
    に残っている。 @book.book_comments でDBから読みなおしてもらえていない。
    @book_comments = @book.book_commentsを
    @book_comment = @book.book_comments.new(book_comment_params)
    の前に持ってくるのかな

    キャンセル

  • 2020/07/08 14:42

    ご回答ありがとうございます。解決致しました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る