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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

1904閲覧

急にでてくるno method error

renren643

総合スコア279

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2017/10/13 16:28

今までは問題なかったのに、急にno method errorがでてきました。
イメージ説明

class CommentsController < ApplicationController before_action :set_comment, only: [:show, :edit, :update, :destroy, :upvote] before_filter :authenticate_user! respond_to :html def index if params[:user_id] @user = User.find(params[:user_id]) @comments = @user.comments else @comments = Comment.all end end def show @comment = Comment.find(params[:id]) end def create @song = Song.find(params[:song_id]) @comment = @song.comments.new(comment_params) @comment.user = current_user respond_to do |format| if @comment.save format.html { redirect_to @song, notice: '投稿に成功しました' } format.json { render json: @comment, status: :created, location: @comment } else format.html { render action: "new" } format.json { render json: @comment.errors, status: :unprocessable_entity } end end end def destroy @comment.destroy respond_to do |format| format.html { redirect_to :back, notice: 'コメントを削除しました' } format.json { head :no_content } end end def upvote @comment.upvote_by current_user redirect_to :back end private def set_comment @comment = Comment.find(params[:id]) end def comment_params params.require(:comment).permit(:song_id, :body, :user_id, :image) end end
class SongsController < ApplicationController before_action :set_song, only: [:show, :edit, :update, :destroy] before_action :authenticate_user!, except: [:index, :show] # GET /songs # GET /songs.json def index if params[:user_id] @user = User.find(params[:user_id]) @songs = @user.songs # ここでアソシエーションが生きる else @songs = Song.all end end # GET /songs/1 # GET /songs/1.json def show @song = Song.find(params[:id]) end # GET /songs/new def new @song = current_user.songs.build end # GET /songs/1/edit def edit end # POST /songs # POST /songs.json def create @song = current_user.songs.build(song_params) respond_to do |format| if @song.save format.html { redirect_to @song, notice: 'Song was successfully created.' } format.json { render :show, status: :created, location: @song } else format.html { render :new } format.json { render json: @song.errors, status: :unprocessable_entity } end end end # PATCH/PUT /songs/1 # PATCH/PUT /songs/1.json def update respond_to do |format| if @song.update(song_params) format.html { redirect_to @song, notice: 'Song was successfully updated.' } format.json { render :show, status: :ok, location: @song } else format.html { render :edit } format.json { render json: @song.errors, status: :unprocessable_entity } end end end # DELETE /songs/1 # DELETE /songs/1.json def destroy @song.destroy respond_to do |format| format.html { redirect_to songs_url, notice: 'Song was successfully destroyed.' } format.json { head :no_content } end end def upvote @song = Song.find(params[:id]) @song.upvote_by current_user redirect_to :back end private # Use callbacks to share common setup or constraints between actions. def set_song @song = Song.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def song_params params.require(:song).permit(:title, :body) end end

もしかしたら知らないうちに何か余計なことをかもしれませんが、ついさっきまで普通に動いていたのに不思議です。
rails4を使っていて、たまにこういったことがあるのですが、これはバグか何かなのでしょうか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

一番考えられるのはSongを削除したのにそれに紐付いたCommentを削除していないという状況です。このようなCommentから関連付けを通じてSongを参照してもnilになります。nilに対してtitleメソッドを呼ぼうとしてエラーになっています。

こういうことが起きないように、Songで、自身が削除されたら紐付いたCommentも削除するようにするようにしてください

has_many :comments, :dependent => :destroy

さらに、DBに外部キー制約を追加してください。

add_foreign_key :comments, :songs, on_delete: :cascade

comment.songnilでないかチェックして処理する、というようなアドホックなコードを書いてはいけません。comment.songがnilになるような状況を作り出さないようにすることを考えないと、どこもかしこもif !なんとか.nil?見たいなコードだらけになっていまいます。

投稿2017/10/14 03:38

編集2017/10/16 00:13
suzukis

総合スコア1449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

renren643

2017/10/14 10:27 編集

add_foreign_key :comments, :books, on_delete: :cascadeの:books,とは、なんでしょうか?この場合でいうと、songsですか? また、外部キーということも初めて聞いて、調べて見たのですが、外部キーの追加の仕方は、ALTER TABLE commnet add_foreign_key :comments, :books, on_delete: :cascadeをターミナルで実行したらいのでしょうか?
suzukis

2017/10/16 00:14

booksはsongsの書き間違いです。add_foreign_keyはマイグレーションのファイルに書いてください。rails g migrationで生成されるやつです。
renren643

2017/10/16 05:13 編集

rails g migration add_foreign_key :comments, :songs, on_delete: :cascadeをターミナルで実行するということでしょうか? また、「has_many :comments, :dependent => :destroy」だけ記述してもうまく機能しているようなのですが、外部キー制約はなんの役目を果たしているのでしょうか?
guest

0

エラー内容の通り、該当箇所でcomment.songがnilであったためにcomment.song.titleが参照できずエラーが発生しています。

index.html.erbと、どの画面操作を行った際に発生したものかも確認する必要がありますが、commentに対応するsongがないなどの状況がどのように発生するのかを確認されるとよいものと思います。

そのような状況が通常操作で発生する場合があるのであれば、comment.songが参照可能かをindex.html.erbにてnilチェック等行い、確認したうえで参照するような処理とされるとよいかと思います。


追記:

コードを読むと、songに対するcommentなのですね。
であれば、suzukisさんのご指摘はごもっともだと思います。

私の回答はcommentとsongは「0または1」の関係と考え、ない場合もあるのであればnilチェック等による場合分けで対処できるのではないか、との回答でした。
songの削除に伴いcomment自体も削除されることに問題がないのであれば、そのような対応(commentの削除)もできると思います。

投稿2017/10/13 17:27

編集2017/10/14 08:10
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問