0
0

More than 3 years have passed since last update.

【初心者向け】ページネーションを付けたページにおける項目番号取得(クラスメソッドの定義まで)

Posted at

はじめに。
クラスメソッドやんわり理解し始めた人間が書いています。
”クラスメソッド 定義”とかで調べても、初心者には理解仕切れない部分があったので、「こんなこと書いてあれば理解の助けになったな」という内容を書いています。
タイトル通り、ページネーションの話から始まり、最後の方で少しクラスメソッドのこと書いてます。

前提(環境)

ruby 2.6.3
rails 5.2.4
db PostgreSQL

gem kaminariを使用してページネーションをしています。

やりたいこと

ページネーションを使用したページで、eachで繰り返し処理したものに、インデクス番号を付けたい。

問題点

eachで繰り返し処理したものの番号を取得する場合、
each.with_index
の使用を考えると思います。

items_controller.rb
def index
  @items = Item.page(params[:page]).per(10)
end
index.html.erb
<% @items.each.with_index do |item,i| %>
  <%= "#{i+1} 、 #{item.title}" %>
<% end %>

<%= paginate @items %>

これだと、ページ毎に番号を取得することとなり、常に1から数えてしまう。

解決策 

クラス名.page(params[:page]).current

で、現在表示しているページが何ページ目かを表示できるため、

index.html.erb
<% @items.each.with_index do |item,i| %>
  <%= "#{(Item.page(params[:page]).current - 1)*10 + i + 1} 、 #{item.title}" %>
<% end %>

とすることで、
1ページ目であれば (1-1)*10+i+1 1〜10を表示
2ページ目であれば (2-1)*10+i+1 11〜20を表示
することができ、解決。

リファクタリング

とても読みづらいコードなのでリファクタリング。
まず、インデックスを0から数える必要がないので

index.html.erb
<% @items.each.with_index(1) do |item,i| %>
  <%= "#{(Item.page(params[:page]).current - 1)*10 + i} 、 #{item.title}" %>
<% end %>

とできる。
更に長ったらし部分をコントローラーに出して

items_controller.rb
def index
  @items = Item.page(params[:page]).per(10)
  page_num = Item.page(params[:page]).current_page
  @base_level = (page_num - 1)*10
end
index.html.erb
<% @items.each.with_index(1) do |item,i| %>
  <%= "@base_level + i} 、 #{item.title}" %>
<% end %>

とできる。
更に更に、クラスメソッドを定義して、コントローラーをすっきりと。

items_controller.rb
def index
  @items = Item.page(params[:page]).per(10)
  @base_level = Movie.base_level(params[:page])
end
item.rb
class Item < ApplicationRecord
  def self.base_level(page)
    (self.page(page).current_page - 1) * 10
  end
end

こんな感じできれい目に実装できるかと思います。

備考(クラスメソッド のこと)

正直私はクラスメソッドの定義はかなり苦戦しました。
そもそもクラスメソッドって何?ってところからだったので。
その点はクラスメソッドでググるればいっぱい出てくると思うので、割愛しますが、私は

params[:page]をクラスメソッドにどう受け渡すか

という点にハマったので少し解説します。
まずクラスメソッドにはparams使えません。
よって

item.rb
class Item < ApplicationRecord
  def self.base_level(page)
    (self.page(params[:page]).current_page - 1) * 10
  end
end

とは書けないのです。
ですがコントローラーで

Movie.base_level(params[:page])

とクラスメソッドで定義したbase_levelの引数に(params[:page])が入っています。
そしてクラスメソッドでは

def self.base_level(page)

と,引数は(page)になっています。
ですので
(params[:page])=(page)
の関係になっていると言えます。

よって今回は、"page(page)"となり、ファッ??って気持ちになるけど(・・・なりませんか?私はなりましたw)

item.rb
class Item < ApplicationRecord
  def self.base_level(page)
    (self.page(page).current_page - 1) * 10
  end
end

という記述になります。

それともう一つ、クラスメソッドはmodelに定義して下さいw
私ははじめ、コントローラーに定義しており、うんともすんとも動かないとうい時間を過ごしてしまいました。

0
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
0
0