質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

Railsの検索システムに実装したページャーの挙動がおかしい

受付中

回答 0

投稿

flag 質問者が18時間前に「まだ回答を求めています」と言っています。

  • 評価
  • クリップ 0
  • VIEW 24

FKM

score 1376

お世話になります。これは以前質問したシステムの続きになります。あれから、試行錯誤の末に検索部分はAjaxを実装することができたのですが、kaminariを使ったページャーの挙動がおかしいままになっており、その原因がわからずに難航しています。

参考にしたページがこちらです
Kaminariをjsonでajax化する

環境

  • Apache2.4.38
  • Ruby2.5.1
  • Rails5.2.3
  • Sqlite3

なお、自分はRailsに不慣れなので、erb、javascriptで記述しています。

プログラム

コントローラ

cities_controller

class CitiesController < ApplicationController
    protect_from_forgery :except => [:index,:get_area,:paginate]
  before_action :get_area, only: [:show, :edit, :update, :destroy]

  # GET /cities
  # GET /cities.json
  PER = 20

  def index
      unless params[:q].blank?
            @q = City.ransack(params[:q])
            @q.sorts = 'population desc' if @q.sorts.empty?
            @cities = @q.result.page(params[:page]).per(10)
            #コンテナのレンダリング
            p_cities = render_to_string(
                partial: 'ajax_container',
                locals: { :cities => @cities}
            )
            #ページャーのレンダリング
            p_pager = render_to_string(
                partial: 'ajax_pager',
                locals: { :cities => @cities },
                remote: true
            )
            if request.xhr?
                render json:{
                    container: p_cities,
                    pager: p_pager
                }
            end
        else
            @q = City.ransack(params[:q])
            @q.sorts = 'population desc' if @q.sorts.empty?
            @cities = @q.result.page(params[:page]).per(10)
        end 
 end

#後略

ルーティング

Rails.application.routes.draw do
  resources :cities
    get 'cities/index', to: 'cities#index'
    post 'cities/index' ,to: 'cities#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

テンプレート

index.html.erb

<%- model_class = City -%>
<div class="page-header">
  <h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1>
</div>

<div class="panel panel-default" id="list">
  <div class="panel-heading">
    <div class="panel-title">検索</div>
  </div>
  <div class="panel-body">
    <%= search_form_for(@q , :id=>'city-form', :remote => true) do |f| %>
      <div class="row">
        <!-- 都道府県名の完全一致検索 -->
        <div class="col-sm-6">
          <div class="form-group">
            <%= f.label :pref_no_eq %>
            <%= f.select :pref_no_eq,Pref::PREF.to_a,{},{class:'form-control'} %>
          </div>
        </div>

        <!-- 市名の部分一致検索 -->
        <div class="col-sm-4">
          <div class="form-group">
            <%= f.label :city_name_cont %>
            <%= f.text_field :city_name_cont, class: "form-control", placeholder: "部分一致" %>
          </div>
        </div>
      </div><!-- @row -->

      <div class="row">
        <!-- 人口の範囲検索 -->
        <div class="form-group">
          <div class="col-sm-12 form-inline">
              <%= f.label :'人口の範囲検索' %>
              <%= f.search_field :population_gteq, class: "form-control", placeholder: "最低値" %><%= f.search_field :population_lteq, class: "form-control", placeholder: "最高値" %>
              <%= f.submit '検索', class: "btn btn-primary btn-search", id: "sbm" %>
              <%= link_to 'クリア', url_for, class: "btn btn-default" %>
              <%= link_to t('.new', :default => t("helpers.links.new")),new_city_path,:class => 'btn btn-primary' %>
          </div>

        </div>
      </div><!-- @row -->
    <% end %>
  <div>
</div>

    <table class="table table-striped" id="tbl">
        <thead>
            <tr>
                <th><%= model_class.human_attribute_name(:id) %></th>
                <th><%= model_class.human_attribute_name(:base_no) %></th>
                <th><%= model_class.human_attribute_name(:city_name) %></th>
                <th><%= model_class.human_attribute_name(:pref_no) %></th>
                <th><%= model_class.human_attribute_name(:population) %></th>
                <th><%=t '.actions', :default => t("helpers.actions") %></th>
            </tr>
        </thead>
        <tbody id="ajax-response-wrapper">
            <%= render 'ajax_container' %>
        </tbody>
    </table>
    <div id="pager"><%= render 'ajax_pager' %></div>

<script type="text/javascript">
        $(function(){
            $(".form-control").each(function(){
                $(this).on('change focusout',function(){
                    $('#sbm').click();
                })
            })
            $("#city-form").on("ajax:success",function(e){
                data = e.detail[0]
                $('#ajax-response-wrapper').empty().append(data.container)
                $('#pager').empty().append(data.pager)
            })
            $("#city-form").on("ajax:fail",function(event,data,status,xhr){
                    alert("fail!")
            })
       })
</script>

パーシャル

_ajax_container.html.erb

<% @cities.each do |city| %>
    <tr id="t">
        <td><%= link_to city.id, city_path(city) %></td>
        <td><%= city.base_no %></td>
        <td><%= city.city_name %></td>
        <td><%= city.pref_no %></td>
        <td><%= city.population %></td>
        <td>
            <%= link_to t('.show', :default => t("helpers.links.show")),
                                    city_path(city), :class => 'btn btn-default btn-xs' %>
            <%= link_to t('.edit', :default => t("helpers.links.edit")),
                                    edit_city_path(city), :class => 'btn btn-default btn-xs' %>
            <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
                                    city_path(city),
                                    :method => :delete,
                                    :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
                                    :class => 'btn btn-xs btn-danger' %>
        </td>
    </tr>
<% end %>


_ajax_pager.html.erb

<%= paginate @cities, window: 2 %>

現行の画面

イメージ説明

仕様

  • 検索機能はRansack、ページャー機能はkaminariを使用(前と変わらず)
  • プルダウンの値変更、またはテキストボックスのフォーカスアウトによって、検索結果をAjaxで返す。Ajaxの手法として、テンプレートをパーシャル化して、レスポンスに対し、一度消去したタグを再度付与する。
  • 検索結果を10件ずつ表示している
  • 検索結果が10件以上となる場合は、ページャーが付与される
  • 検索結果が10件以下となる場合は、ページャーは付されない

発生している問題

  • ページャーの遷移がおかしく、最初に読み込んだ状態から、10件以上検索される結果を表示し、その画面のページャーから2ページめを押しても、1ページ目の表示が残ります。その状態でもう一度2ページ目を押すと、次のページに遷移します。

ところが、キャッシュの関係なのかそのバグを再現できない場合もあります。また、ページャー無しの検索結果から再びページャーありの検索結果となった場合にページ遷移を行うと、同様のバグが起こったりします。

やってみたこと

  • ページャーにremote: trueを記述してみた → ページャー機能のAjax自体が機能しなくなりました
  • テンプレートのパーシャル部分を削除した → ページャーの遷移後に表示されなくなってしまいました

ほかにもコントローラのメソッドを通常制御とAjaxで分けてみたり、パーシャルの記述を変えてみたり色々試行錯誤してみたのですが、解決しないので皆様の助力を仰がせていただきます。

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • m.ts10806

    2019/12/03 15:14

    回答依頼いただきましたがRuby未経験ですので期待にはお答えできません

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる