Rails7 kaminari를 이용한 Pagination기능 추가

Posted by negabaro kim on Saturday, December 9, 2023 Tags: rails/kaminari   6 minute read

kaminari라는 gem을 이용해서 레일즈에서 Pagination기능구현 하는법을 정리해봤다.

Pagination이란 게시판에 100개의 글이 있을 경우 이글을 페이지 번호를 매겨 보기쉽게 표시하는 기능이다.

image

사전에 rails로 퀴즈어플 만들어보기(CRUD편)에서 만든 WritingQuiz모델의 index.html.erb에 이Pagination기능을 넣어보기로 하자.

kaminari Gem추가후 bundle install

kaminari는 Rails에서 간단히 Pagination기능구현을 하기위해 사용되는 유명한 Gem이다.

# Gemfile
gem 'kaminari'

컨트롤러 수정

지금까지 WritingQuiz.all를 이용해서 전체 데이터를 가져왔었는데 해당 설정을 커맨트하고 이하 page메소드에 params[:page]를 얹혀서 보내준다.

뒤에서 알았지만 xx.all과 동일한 데이터를 취득 가능했다.

#app/controllers/writing_quizzes_controller.rb
  def index
      #@wquizzes = WritingQuiz.all
      @wquizzes = WritingQuiz.page(params[:page])
  end

뷰 설정(인덱스 페이지에 페이지네이션 설정 추가)

뷰에서는 이하 2개의 설정을 추가해준다.

 <%= page_entries_info @wquizzes %>
 <%= paginate @wquizzes %> #페이지네이션링크를 추가하는부분
#app/views/writing_quizzes/index.html.erb
<div class="main posts-index">
 
  <div class="container">
    <%= page_entries_info @wquizzes %>
    <% @wquizzes.each do |w| %>
      <div class="posts-index-item">
        <div class="post-left">
          <%= link_to w.id , writing_quiz_path(w.id) %>
        </div>
        <div class="post-right">
          <div class="post-user-name">
           문제: <%= w.question %>
          </div>
          정답: <%= w.answer %>
        </div>
      </div>
    <% end %>
    <%= paginate @wquizzes %>
  </div>
</div>

여기까지만 설정이 끝나면 Rails를 재기동해준다.(재기동 안하면 반영안됨)

<%= paginate @xx %>

<%= paginate @wquizzes %>

설정에 의해 이하와 같은 페이지네이션 링크가 추가된걸 알 수 있다.

image

page_entries_info란

<%= page_entries_info @wquizzes %>

뷰에서 추가한 위 설정으로 화면 상단에 이러한 페이징정보를 표시할 수 있다.

image

kaminari view커스텀

기존의 kaminari화면을 커스텀할때 이하 커맨드를 실행하면

rails g kaminari:views default

or 혹시 생성이 안된다면

rails g kaminari:views default -e erb

로 실행해보자.

app/views/kaminari이하에 템플릿파일이 생성되므로 해당 부분을 커스텀 가능하게 한다.

kaminari커스텀 설정

rails g kaminari:config
      create  config/initializers/kaminari_config.rb

코맨트 되있는 부분이 디폴트 설정이다. 해당부분을 코맨트 아웃하고 수정하면 설정이 변경된다.

# config/initializers/kaminari_config.rb
Kaminari.configure do |config|
  # config.default_per_page = 25 # 1페이지당 항목수
  # config.max_per_page = nil    # 1페이지당 최대수
  # config.window = 4            # ex 값이 2일 경우 .. 2 3 (4) 5 6 ..
  # config.outer_window = 0      # ex 값이 2일 경우 .. (4) .. 99 100
  # config.left = 0              # ...로 표시될때 왼쪽 표시숫자
  # config.right = 0             # ...로 표시될때 오른쪽 표시숫자
  # config.page_method_name = :page # 메소드명
  # config.param_name = :page    # pagination의 파라메터 명 
end

모델별 설정

config/initializers/kaminari_config.rb 부분을 수정시에는 Rails프로젝트 전체에 적용되는데 이하와 같이 특정 모델에게만 적용하는 설정도 가능하다

#app/models/writing_quiz.rb

class Shop < ActiveRecord::Base
  paginates_per 5  # 1페지당 5항목 표시
end

뷰 설정

#app/views/writing_quizzes/index.html.erb
...
<%= paginate @wquizzes, outer_window: 4 %>

그외

컨트롤러 설정없이 view부분만 추가해보면 어떤 에러가 나올까.

<%= paginate @wquizzes %>

이하와 같은 에러가 발생했다.

undefined method `total_pages' for #<WritingQuiz::ActiveRecord_Relation:0x007fc24ffe5ad8>

undefined method total_pages에러가 발생하는걸 봐서는 메소드명의 디폴트값은 total인것 같다.

간단히 kaminari에 대해서 알아봤다.

memo

1. tailwind-css사용시 rails g kaminari:views default실행이 안됨(2023/12/10추가)

rails g kaminari:views default실행시 아무것도 생성이 안되는 버그가 있음 해결방법으로 -e erb를 붙여주면 생성됨 rails g kaminari:views default -e erb

2. ActionView::Template::Error: No such file or directory 에러(2023/12/10추가)

=> #<ActionView::Template::Error: No such file or directory @ rb_sysopen - /app/app/views/kaminari/_page.html.erb>

랜덤하게 이런에러가..뭐지. rails g kaminari:views default실행안되서 예전 프로젝트 kaminari코드를 갖다붙였는데 뭔가 문제가 있는듯. rails g kaminari:views default -e erb로 생성하니 문제없음

3. ransack, decorate등을 같이 사용할때(2023/12/10추가)

decorate한 값에 page를 넣으면 에러가 발생 예를들어 아래와 같은 코드면 동작하지 않음.

@q = Contract.ransack(params[:q])
@contracts = @q.result.order(id: :desc).decorate.page(params[:page])

반대로 해도 마찬가지 @q.result.order(id: :desc).page(params[:page]).decorate

해결방법을 몰라서 인스턴스를 따로 만들었다.

@q = Contract.ransack(params[:q])
@paginated_contracts = @q.result.order(id: :desc).page(params[:page])
@contracts = @paginated_contracts.decorate

이런식으로 해서paginate부분에만 paginated_contracts를 사용하게 함

<%= paginate @paginated_contracts %>

4. kaminari의 기본 locals설정 바꿔주는 법

config/application.rb에 config.i18n.default_locale = :ko추가

confing/locals/kaminari_ko.yml에 아래 설정 추가

ja:
  views:
    pagination:
      first: "&laquo;"
      last: "&raquo;"
      previous: "&lsaquo;"
      next: "&rsaquo;"
      truncate: "..."
  helpers:
    page_entries_info:
      one_page:
        display_entries:
          zero: ""
          one: "<strong>1-1</strong>/1건중"
          other: "<strong>1-%{count}</strong>/%{count}건중"
      more_pages:
        display_entries: "<strong>%{first}-%{last}</strong>/%{total}건중"
  activerecord:
  errors:
    messages:
      record_invalid: "validation에 실패했습니다.: %{errors}"