LoginSignup
1
0

More than 5 years have passed since last update.

groupしたら「Hash can't be coerced into Fixnum」が出たけど、pしたら大丈夫だったのはなぜ?

Posted at

総件数が表示される一覧画面を作っていたところ、エラーが発生。
総件数の部分はhelperで定義されていて、今まで特に問題なく動いていたのに・・・

  def page_navi(objects, class_name = 'per_page')
   return if objects.nil?
   html  = objects.total_count.to_s
   html += '件中 '
   html += "#{ objects.limit_value * objects.offset_value / objects.limit_value + 1 }"
   html += '~'
   html += "#{ objects.limit_value * objects.offset_value / objects.limit_value + objects.size }"
   html += '件を表示  '
   html += select_tag :per_page, options_for_select(per_pages_for_select, params[:per_page]), class: class_name
   html += '件毎に表示にする'
   html.html_safe
  end

エラーを見るとどうやらobjects.sizeが怪しい・・・

よくわからないけど、とりあえずobjectsの中身を確認してみようと思って、

  def page_navi(objects, class_name = 'per_page')
   return if objects.nil?
   p objects
   html  = objects.total_count.to_s

と書いて確認してみたところ、

なんとエラーが発生しなくなった!!

おいおい意味わかんねーぞといろいろ試してみたところ、

   html += "#{ objects.limit_value * objects.offset_value / objects.limit_value + objects.length }"

にしたら大丈夫だった
ちなみに objects.count にすると p をやってもダメだった

sizeとcountとlengthで違いがあるというのは噂レベルで知っていたけど、
いい機会なのでちょっと調べてみたら、
【Rails】sizeとcountとlengthについて
こちらのページがわかりやすかった

カウンタキャッシュを使っていない場合、
sizeは、ロード時には配列の要素数を返し、未ロード時にはcount文を発行しますし、
lengthは、ロード時には配列の要素数を返しますが、未ロード時にはselect * ~を発行したのち配列の要素数を返します。
そんでもって、
countはどんなときであれ毎回count文を発行します。

詳しくはわかってないけど、どうやら自分の作ったクエリではcount文がうまく作れないため、
sizeで作っていたときには未ロード時にcount文を作ろうとしてエラーになっていたらしい。

ちなみに今回作ったクエリはグルーピングしてました。
(グルーピングの部分を外すとsizeでも問題なく動きました。)

lengthを使うとパフォーマンスに影響が出るそうだけど、
今回lengthを使う場面は必ず一覧画面とセットなので、
まぁそれほど影響は出ないと信じ、とりあえずlengthで突っ走ります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0