0

I have a search form with pagination. Both things work OK separately, but if I search and then load the next page, the search parameters are forgotten and kaminari shows results regardless of what search options I selected.

I have read through the docs, and other stackoverflow posts but I'm not having any luck.

My index page has

<%= search_form_for @q, html: { id: "gig_search_form" }, remote: true do |f| %>
bla bla bla...
<% end %>
<%= link_to_next_page @gigs, 'Next Page', :remote => true %>

index.js.erb

<% if params[:page] %> 
 $('.gig-search-list').append("<%= j render(partial: 'gigs') %>");
<% else %>
 $('.gig-search-list').html("<%= j render(partial: 'gigs') %>");
<% end %>

gigs partial:

    <% @gigs.each do |gig| %>
      bla bla bla... 
    <% end %>

Now, I have tried a few tings in my controller but I'm always gettings the same results. Originally I had;

def index
      if params[:search].present?
        @q = Gig.notexpired.where(:filled => false).near(params[:search], 500, :order => 'distance' ).ransack(params[:q])
      else
        @q = Gig.notexpired.where(:filled => false).ransack(params[:q])
      end
        @allgigs = @q.result(distinct: true)
        @gigs = @q.result(distinct: true).page(params[:page]).per(5)
      respond_to do |format|
      format.js
      format.html
    end
  end

Then;

def index
      if params[:search].present?
        @q = Gig.notexpired.where(:filled => false).near(params[:search], 500, :order => 'distance' ).ransack(params[:q])
      else
        @q = Gig.notexpired.where(:filled => false).ransack(params[:q])
      end
        @allgigs = @q.result(distinct: true)
        @gigs = Kaminari.paginate_array(@allgigs).page(params[:page]).per(5)
      respond_to do |format|
      format.js
      format.html
    end
  end

Then I tried to separate them;

def index
      if params[:search].present?
        @q = Gig.notexpired.where(:filled => false).near(params[:search], 500, :order => 'distance' ).ransack(params[:q])
      else
        @q = Gig.notexpired.where(:filled => false).ransack(params[:q])
      end
      @allgigs = @q.result(distinct: true)
      if @allgigs.present?
        unless @allgigs.kind_of?(Array)
          @gigs = @allgigs.page(params[:page]).per(5)
        else
          @gigs = Kaminari.paginate_array(@allgigs).page(params[:page]).per(5)
        end
      end
      respond_to do |format|
      format.js
      format.html
    end
  end

But I get the same result each time. I can see on the console that when I load more pages, the search parameters are not included.

How can I link the two things together and paginate the search results correctly?


UPDATE:

Server log after loading 'next page' using @chaitanya's answer. I have previously added search params.

Started GET "/gigs?locale=en&page=2" for 127.0.0.1 at 2016-06-29 14:45:53 +0200
Processing by GigsController#index as JS
  Parameters: {"locale"=>"en", "page"=>"2"}
  Gig Load (10.3ms)  SELECT DISTINCT "gigs".* FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:53.493341') AND "gigs"."filled" = $1  [["filled", "f"]]
  Gig Load (1.2ms)  SELECT  DISTINCT "gigs".* FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:53.493341') AND "gigs"."filled" = $1 LIMIT 5 OFFSET 5  [["filled", "f"]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 7]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 2]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 6]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 8]]
  Rendered gigs/_gigs.html.erb (13.4ms)
   (0.5ms)  SELECT DISTINCT COUNT(DISTINCT "gigs"."id") FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:53.493341') AND "gigs"."filled" = $1  [["filled", "f"]]
  Rendered gigs/index.js.erb (17.2ms)
Completed 200 OK in 54ms (Views: 21.4ms | ActiveRecord: 13.0ms)

Server log when filtering with search form:

Started GET "/gigs?locale=en&utf8=%E2%9C%93&search=&q%5Bdate_gteq%5D=&q%5Bdate_lteq%5D=&q%5Bgenres_id_in%5D%5B%5D=&q%5Bsalary_cents_gteq_euros%5D=0.00&q%5Bsalary_cents_lteq_euros%5D=210.00" for 127.0.0.1 at 2016-06-29 14:45:47 +0200
Processing by GigsController#index as JS
  Parameters: {"locale"=>"en", "utf8"=>"✓", "search"=>"", "q"=>{"date_gteq"=>"", "date_lteq"=>"", "genres_id_in"=>[""], "salary_cents_gteq_euros"=>"0.00", "salary_cents_lteq_euros"=>"210.00"}}
  Gig Load (0.6ms)  SELECT DISTINCT "gigs".* FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:47.973892') AND "gigs"."filled" = $1 AND ("gigs"."salary_cents" >= 0 AND "gigs"."salary_cents" <= 21000)  [["filled", "f"]]
  Gig Load (0.5ms)  SELECT  DISTINCT "gigs".* FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:47.973892') AND "gigs"."filled" = $1 AND ("gigs"."salary_cents" >= 0 AND "gigs"."salary_cents" <= 21000) LIMIT 5 OFFSET 0  [["filled", "f"]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 8]]
  CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 7]]
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 3]]
  Rendered gigs/_gigs.html.erb (12.2ms)
   (0.4ms)  SELECT DISTINCT COUNT(DISTINCT "gigs"."id") FROM "gigs" WHERE (gigzonetime > '2016-06-29 12:45:47.973892') AND "gigs"."filled" = $1 AND ("gigs"."salary_cents" >= 0 AND "gigs"."salary_cents" <= 21000)  [["filled", "f"]]
  Rendered gigs/index.js.erb (15.6ms)
Completed 200 OK in 33ms (Views: 19.9ms | ActiveRecord: 5.7ms)
Rob Hughes
  • 876
  • 2
  • 13
  • 32

2 Answers2

1

try following code to carry your params to next page

= link_to_next_page @gigs, "Next Page", :remote => true, :params => params
chaitanya
  • 1,974
  • 3
  • 17
  • 35
  • Thanks for your quick reply, I tried that with all 3 versions of my controller but I'm still getting the same result. – Rob Hughes Jun 29 '16 at 12:41
  • actually first version should work, can you paste log when you make search and click on pagination – chaitanya Jun 29 '16 at 12:43
  • does pagination code is in the partial? so we can update it after ajax? – chaitanya Jun 29 '16 at 12:53
  • Ill move it to the partial now and check. – Rob Hughes Jun 29 '16 at 12:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/115968/discussion-between-chaitanya-and-rob-hughes). – chaitanya Jun 29 '16 at 12:57
  • Well I feel like an idiot, I had some conflicting javascript that was interfering with the 'next page' button getting loaded properly. This answer is correct and I will update my question with the answer. – Rob Hughes Jun 29 '16 at 13:34
  • @RobHughes do **not** update your question with the answer, accepting is the correct way – Petter Friberg Jun 29 '16 at 13:35
  • OK then I will add that I used version 1 of my controller and I put the 'answer' in the partial. Maybe somebody else might find this useful... – Rob Hughes Jun 29 '16 at 13:39
0

You should add the #page and #per methods to the query itself. Kaminari.paginate_array actually takes a slice from the whole array which is not very efficient.

Here's a snippet

def index
  if params[:search].present?
    @q = Gig.notexpired.where(:filled => false).page(params[:page]).per(5).near(params[:search], 500, :order => 'distance' ).ransack(params[:q]).results
  else
    @q = Gig.notexpired.where(:filled => false).page(params[:page]).per(5).ransack(params[:q]).results
  end

#...

Then use the Kaminari paginate helper in your view

<%= paginate @q %>
Oss
  • 4,232
  • 2
  • 20
  • 35