見出し画像

Rails ジャンル機能②

前回作ったジャンル機能にちょっとした機能を付け足していきます。
まずは以下のようにジャンル毎に本の数を表示する実装を付け加えます。

ジャンル毎の本の数を表示する

まずはジャンル毎に本の数をカウントするためのメソッドを作成します。
最初にテストを以下のように修正し、実行してレッドになることを確認します。

describe '.group_by_name_with_book_count' do
  let(:genre_name) { 'test' }
  let(:book_count) { 3 }

  before do
    genre = create(:genre, name: genre_name)
    create_list(:book, book_count, genre:)
  end

  it 'name 毎に group し本の数をカウントする' do
    results = Genre.group_by_name_with_book_count
    expect(results.first.name).to eq(genre_name)
    expect(results.first.book_count).to eq(book_count)
  end
end

まだメソッドを追加していないのでテストはレッドになります。そこで、app/models/genre.rb mに以下を追加します。

def self.group_by_name_with_book_count
  joins(:books).group(:name).select(:id, :name, 'COUNT(books.id) as book_count')
end

そして、テストを再度実行します。

bundle e rspec spec/models/genre_spec.rb

すると、今度はテストの結果がグリーンになると思います。
ジャンル毎の本の数をカウントするロジックはできたので、次は処理した結果をビューに表示する処理を作成していきます。
app/controllers/genres_controller.rb を以下のように修正します。

def index
  @genres = Genre.group_by_name_with_book_count
end

そして、ビューに表示するため、app/views/genres/index.html.erb を以下のように修正します。

<% @genres.each do |genre| %>
  <%= link_to genre.name, genre_books_path(genre) %>(<%= genre.book_count %>)<br />
<% end %>

ここまでの修正を加えるとジャンル毎の本の数が表示されるようになっていると思います。

ページネーションを追加する

現在の実装ですと、ジャンル毎の検索を行なった後に表示される本の数がとても多くなっていると思います。
1ページに表示されるデータの件数を少なくし、1ページ目に表示されていないデータは2ページ目以降に表示されるようページネーションを追加します。
ページネーションを実装する際、kaminari を使うことが多いと思うので習慣にならって kaminari を使って実装したいと思います。
Gemfile に以下を追加します。

gem 'kaminari'

そして、bundle install を実行します。

bundle install

これで kaminari を使えるようになりました。
ページネーションを追加するため、app/controllers/genres/books_controller.rb を以下のように修正します。

@books = @genre.books.page(params[:page])

kaminari の設定オプション によるとデフォルトの1ページあたりの件数は25ということです。
ビューにページネーションのリンクを表示するため、以下のヘルパーメソッドを呼び出すように以下を app/views/genres/books/index.html.erb に追加します。

<%= paginate @books %>

すると、以下のようにページネーションができるような表示に切り替わると思います。


Next や Last 、数値のリンクをおすとそれらに応じたページに遷移できるようになっていると思います。
これでちょい足しの機能は完成です。

この記事が気に入ったらサポートをしてみませんか?