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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Q&A

解決済

2回答

650閲覧

Railsチュートリアル13章 @feed_itemsがnilになる?

Yuuki2918

総合スコア17

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

0グッド

2クリップ

投稿2019/06/14 10:18

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
現在、rails チュートリアルを利用して学習中です。
13章の中盤あたり、13.3.3 フィードの原型という節の解説でどうしても引っかかる部分があり投稿しました。

本節ではtwitterのような短い投稿フォーム(micropostフォーム)を静的なhomeページに表示させ、その横に投稿の一覧を表示させる(feed_items)という作業をしています。
その文中で、「投稿内容が空欄(投稿が失敗)の際に、renderで同じhomeページを出力する際にエラーが発生する」という解説があります。

現時点では、新しいマイクロポストの作成は図 13.15で示したように期待どおりに動作しています。ただしささいなことではありますが、マイクロポストの投稿が失敗すると、 Homeページは@feed_itemsインスタンス変数を期待しているため、現状では壊れてしまいます。

この部分が理解できずにいます。ですのでその後に続く

最も簡単な解決方法は、リスト 13.50のように空の配列を渡しておくことです。残念ですが、この場合はページ分割されたフィードを返してもうまく動きません。

という一文も理解でできていません。
ご教授いただきたく投稿しました。よろしくお願いします。
(何か記載する情報が足りない場合はご指摘ください)

発生している問題・エラーメッセージ

undefined method `any? for nil:NilClass

エラー個所は
<% if @feed_items.any? %>で、解説の

Homeページは@feed_itemsインスタンス変数を期待しているため、現状では壊れてしまいます。

という言葉と一致していると思われます。
undefined method any? for nil:NilClassというエラーが出ているということは、@feed_itemsがnilになっているということだと思うのですが、なぜnilになってしまうのかが知りたいです。
renderでhomeページを表示

該当のソースコード

home.html.erb (homeページのソース)

html

1<% if logged_in? %> 2 <div class="row"> 3 <aside class="col-md-4"> 4 <section class="user_info"> 5 <%= render 'shared/user_info' %> 6 </section> 7 <section class="micropost_form"> 8 <%= render 'shared/micropost_form' %> 9 </section> 10 </aside> 11 <div class="col-md-8"> 12 <h3>Micropost Feed</h3> 13 <%= render 'shared/feed' %> 14 </div> 15 </div> 16<% else %> 17 . 18 . 19 . 20<% end %>

<%= render 'shared/feed' %>のパーシャル

ruby

1 2<% if @feed_items.any? %> 3 <ol class="microposts"> 4 <%= render @feed_items %> 5 </ol> 6 <%= will_paginate @feed_items %> 7<% end %> 8

homeコントローラー(@feed_itemsの定義があります)

ruby

1 def home 2 if logged_in? 3 @micropost = current_user.microposts.build 4 @feed_items = current_user.feed.paginate(page: params[:page]) 5 end

上記コード、feedメソッド部分(User model)

ruby

1 def feed 2 Micropost.where("user_id = ?", id) 3 end

micropostを作成する際のcreateアクションの定義

ruby

1class MicropostsController < ApplicationController 2 before_action :logged_in_user, only: [:create, :destroy] 3 4 def create 5 @micropost = current_user.microposts.build(micropost_params) 6 if @micropost.save 7 flash[:success] = "Micropost created!" 8 redirect_to root_url 9 else #投稿が失敗 10 @feed_items = [] #これを挿入しないとエラーが出る 11 render 'static_pages/home'  12 end

試したこと

何回かキーワードになりそうな単語を使い調べてみたのですが(render rails 変数,, etc)わかりませんでした。
ものすごく基本的なことを質問してしまっていそうで怖いのですが、ご回答いただければ幸いです。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

下記の1行を足さないとエラーになる原因を知りたいという理解で大丈夫でしょうか?

ruby

1 @feed_items = [] #これを挿入しないとエラーが出る

まず、投稿に失敗した際は@micropost.savefalseになり、else内に行くことになります。
その後render(static_pages/home)で、つまりhome.html.erbが表示されます。

このときhome.html.erbに渡される変数は、def createからrender 'static_pages/home'の間で@の付いた変数に入れられたものです。

この場合だと、
@micropost = current_user.microposts.build(micropost_params)
と、
@feed_items = []
になります。

ruby

1 def create 2 @micropost = current_user.microposts.build(micropost_params) 3 if @micropost.save 4 flash[:success] = "Micropost created!" 5 redirect_to root_url 6 else #投稿が失敗 7 @feed_items = [] #これを挿入しないとエラーが出る 8 render 'static_pages/home'  9 end

では@feed_items = []がないとどうなるかというと、home.html.erbの描画時に@feed_itemsの中に何も入っていないということになります。
つまり@feed_itemsにはnilが入ります。

nilany?という関数を持たないため、shared/feed@feed_items.any?でエラーになるわけです。

投稿2019/06/14 17:26

dorarep

総合スコア102

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

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

Yuuki2918

2019/06/15 07:37

お返事ありがとうございます! > 下記の1行を足さないとエラーになる原因を知りたいという理解で大丈夫でしょうか? そうです、@feed_itemsがnilだからエラーが起こる事までは把握できたのですが、なぜnilになるかがわかりませんでした。 ですが、お二人から頂いた解説で、「どこを理解してなかった」が理解できました。 どうやらrenderの動作がまだ把握できていなかったようです。 renderでページを描写する際の変数の読み込みの理解がまだ足りていないようでした。 ご回答いただいた後にチュートリアルには記載されてなかったですが、自分で少しコードをいじって色々と調べてみました。誰かの参考になるかもしれないので記載します。 --------------------------------------------- チュートリアルのサンプルでは、投稿が失敗した場合はエラー文を表紙させる代わりに、@feed_itemsに空の配列を入れてるので過去の投稿一覧が消えてしまっていました。 出来れば、1,エラー文を表示させつつ 2,過去の投稿も表示させたい と思いコードを修正しました。 def createの投稿失敗時の動作 else #投稿が失敗 @feed_items = [] #これを挿入しないとエラーが出る render 'static_pages/home'  end を else #投稿が失敗 redirect_to root_path (homeページ)  end と変更した場合(renderではなくredirectを使って再描写)は、発生したエラーも含めてページが更新された状態になるので、過去の投稿は表示されましたがエラー内容が表示されませんでした。 次に else #投稿が失敗 @feed_items = current_user.feed.paginate(page: params[:page]) render 'static_pages/home'  end と、失敗時に@feed_itemsにhomeコントローラーと同じ内容を入れておくことで、renderした後、エラーを表示しつつ過去の自分の投稿も表示させることができました。 こちらの方がより実際のSNSっぽいかなぁと思います。 --------------------------------------------- お二人からご回答を頂けて本当に助かりました、ありがとうございます。精進します!
guest

0

any? は配列のようなオブジェクトに使えるmethodなので nil には使えません。

@feed_items = current_user.feed.paginate(page: params[:page])current_userfeed を持っていれば any? が使えるようになりますが、そもそも feed が存在せず、 @feed_itemsnil が入ってしまうと nil.any? となってしまうのでエラーになってしまいます!

undefined method any? for nil:NilClassというエラーが出ているということは、@feed_itemsがnilになっているということだと思うのですが、なぜnilになってしまうのかが知りたいです。

@feed_itemsnil になる原因は、 current_userfeed を一つも保持していないときがあるからです!

投稿2019/06/14 10:33

t_kusakabe74

総合スコア549

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

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

Yuuki2918

2019/06/14 15:40

t_kusakabe74 さん ご回答ありがとうございます。 .anyやエラーの原因の解説ありがとうございます!理由は理解できたのですが、追加で新しい疑問点が一つできてしまったので追記しました。 ご回答で > @feed_items が nil になる原因は、 current_user が feed を一つも保持していないときがあるからです! ということですが、今回エラーが起きたcurrent_userには過去にもmicropostに投稿がありました。 つまりhomeページで投稿を失敗する前までは current_userがfeedを保持している状態でした。(過去の投稿が表示されていました) その後投稿に失敗した際にfeedを一つも保持していない(=nilになった)状態になったという理解でいいと思うのですが、これの原因は一旦なんなのでしょうか? いきなりnilになっているので Micropost.where("user_id = ?", id)のidが取得できていない?など色々考えていたのですが。。。ご回答いただけたら幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問