😽

【Rails】will_paginateを使用時にgonの中身が更新されない問題

2023/02/28に公開

概要

will_paginateを用いて、ページの切り替えを行った際に渡されるgonの中身が更新されない問題が発生したので、その原因と対処法をメモ。

gonについて

gonについての使い方は下記のURLがわかりやすいので省略
https://nekorails.hatenablog.com/entry/2018/10/16/100750

原因

ページの切り返しに、gonの更新が行われないのは、turbolinksが有効だったために更新されなかった。
turbolinksとは、簡単にいうとjs, cssの読み込みを初回時に行い次回以降の読み込み処理を省略することで高速化する処理をしているのものだ。

おそらくこれが悪さをしている。

対処法(面倒)

一番はページの切り返しにturbolinksをfalseにすること。
ただし、これは簡単にはできない。
下記のようにレンダラーをカスタムすることでしか実現できないのだ

config/initializers/custom_renderer.rb
require 'will_paginate/view_helpers/action_view'
require 'will_paginate/view_helpers/link_renderer' 

class CustomPaginateRenderer < WillPaginate::ActionView::LinkRenderer
  def container_attributes
    { class: 'pagination' }
  end

  def html_container(html)
    child = tag(:ul, html, container_attributes)
    tag(:nav, child)
  end

  def page_number(page)
    if page == current_page
      '<li class="page-item active" data-turbo="false">' + link(page, page, rel: rel_value(page),class: 'page-link') + '</li>'
    else
      '<li class="page-item" data-turbo="false">' + link(page, page, rel: rel_value(page),class: 'page-link') + '</li>'
    end
  end

  def previous_page
    num = @collection.current_page > 1 && @collection.current_page - 1
  previous_or_next_page(num, '<span aria-hidden="true">&laquo;</span>')
  end

  def next_page
    num = @collection.current_page < total_pages && @collection.current_page + 1
  previous_or_next_page(num, '<span aria-hidden="true">&raquo;</span>')
  end

  def previous_or_next_page(page, text)
    if page
      '<li class="page-item" data-turbo="false">' + link(text, page, class: 'page-link') + '</li>'
    else
      '<li class="page-item disabled" data-turbo="false">' + link(text, page, class: 'page-link') + '</li>'
    end
  end
end
application_helper.rb
def will_paginate(coll_or_options = nil, options = {})
  if coll_or_options.is_a? Hash
    options = coll_or_options
    coll_or_options = nil
  end
  unless options[:renderer]
    options = options.merge renderer: CustomPaginateRenderer
  end
  super *[coll_or_options, options].compact
end

正直ちょっとめんどくさい。他への影響もわからないし。。。

対処法(簡単)

だったら、毎回読み込まれるような位置に= Gon::Base.render_dataを配置しとけば、もしかして毎回読み込まれるのでは?と仮説を立ててみると、以下のようなissuesがHit。
https://github.com/gazay/gon/issues/106

なるほど、bodyタグ内で定義してしまえばいいのか!

sample.slim
doctype html
html
  head
    title 管理画面

    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag    'cms/application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'cms/application', 'data-turbolinks-track': 'reload'

  body
   # 省略
   = Gon::Base.render_data

解決した。

まとめ

たまには楽しても....いいよね。。。笑

Discussion