複数データのランダム取得
以下のコードでランダムに4冊の本のデータを取得しています。
controller
1def sample 2 @books = Book.offset(rand(Book.count)).first(4) 3end
取得した4冊の本のタイトルをviewで出します。
html
1<ol> 2 <% @books.each do |book| %> 3 <li> 4 <%= book.title %> 5 </li> 6 <% end %> 7</ol>
ここまでは問題なく表示できます。
表示例)
0. 罪と罰
0. こころ
0. 地獄変
0. 斜陽
リロードすると…
0. 地獄変
0. 砂の器
0. 3匹のおっさん
0. 吾輩は猫である
(たぶんID落ちによる)エラー
上記のviewではeachを使って取得したデータ全て(4冊)を表示しました。
今度は取得したデータそれぞれについて個別に表示させようと思い、以下のように追記しました。
html
1<ol> 2 <% @books.each do |book| %> 3 <li> 4 <%= book.title %> 5 </li> 6 <% end %> 7</ol> 8 9 ↓ 以下を追記 10<%= @books.first.title %> 11<%= @books.second.title %> 12<%= @books.third.title %> 13<%= @books.fourth.title %>
すると、基本的には問題なく表示できるのですが、リロードした際、時折エラーが起きるようになりました。エラー内容は以下のものです。
undefined method `title' for nil:NilClass
このエラー文に該当する箇所は、先ほど追記したうちの
<%= @books.second.title %>か
<%= @books.third.title %>か
<%= @books.fourth.title %>です。
secondで引っ掛かったり、fourthで引っ掛かったり、その時々です。
エラーになる場合、おそらくcontrollerがデータを集める時点で空のIDを含んでいるのだと思いました。
例)Bookデータのidが1~10あり、そのうち5,6,7が削除済みだったとする。 controllerでランダムに取得した4つのデータのidが1,4,6,9だった場合、削除済みのid=6はnilなので <%= @books.third.title %> でエラーとなる。これより上記のeach文は、取得できた1,4,6,9のうちtitleのある1,4,9のみ表示している(エラーなので確認できないが)。
こんなことだろうな、これはIDに抜けがないときだけ使おう、と思っていたのですが…
いや待てよ、たしか… エラーが起きたのは <%= @books.second.title %> などを追記してからだから、
追記部分を削除してeach文だけ残すと…
あれ? 不思議とエラーは起こらず毎回必ず4件のtitleがランダムに取得できます。
もうわかりません。
- ※Bookデータは計20件入っています。
- ※20件のうちいくつか削除したデータがあります。
- ※リロードすると4~5回に1回のペースで上記エラーが起こります。
- ※追記した箇所を削れば(each文だけでは)エラーは起きません。
- ※追記があっても、each文の箇所ではエラーは起きません。
- ※<%= @whgs.first.title %>でエラーになったことはありません。
教えていただきたいこと
- エラーの起きる原因と、なぜeach文だけではエラーにならず毎回4件取れるのか。
- エラーの起きる原因がIDが欠けていることだった場合、欠けたIDをうまく避けて4件のレコードを取得するには、controller側にどう書けばいいか。
controllerの記述を以下のものに変えてみても結果は全く同じでした。
controller
1def sample 2 @books = Book.where('id >= ?', rand(Book.first.id..Book.last.id)).first(4) 3end
プログラミング初心者です。よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/20 01:49
2018/09/23 16:03
2018/09/24 05:53
2018/09/25 05:04