Tire search and will_paginate - undefined method `offset' - ruby-on-rails

After headaches with ThinkingSphinx and Solr/Sunspot, we're trying out ElasticSearch and Tire as our search back-end - but I've hit a problem.
Here's my search command in the controller:
#results = Item.search params[:search], :page => ( params[:page] || 1 ), :per_page => 20
And this is the problem section of the view:
<%= page_entries_info #results %>
The error message I'm getting is
undefined method `offset' for #<Tire::Results::Collection:0xa3f01b0>
but only when there is more than one page's worth of results. If there are less than 20 items returned, then they get shown fine.
The only similar reported issue I could find elsewhere was solved by passing the :page and :per_page parameters into the search function, but I'm already doing that, to no avail.

Tire has a Pagination module but it doesn't define offset. You could file an issue with them to add it, but in the meantime you can monkeypatch it in your app:
Tire::Results::Pagination.module_eval do
def offset
(#options[:per_page] || #options[:size] || 10 ).to_i * (current_page - 1)
end
end

in my testapp, results are paginated just fine, with will_paginate 3.0 and tire 0.3. I wasn't aware will_paginate needed the offset method.
I've added it, however, copying over the "lint" test from will_paginate specs: https://github.com/karmi/tire/commit/e0e7730. Should be part of the next release.

Related

why is will_paginate throwing an expected 1 given 2 error?

I have an issue where legacy code for pagination was implemented prior to me being hiring failed randomly today. I am running a heroku app with rails and using will_paginate for pagination. In my controller I have
`
def index
#publications = Publication.paginate(page: params[:page], per_page: 11).order('sort_date DESC')
end
`
in my view i have
`
<div class="container">
<%= will_paginate #publications %>
</div>
`
It throws the following error(which is leading to a 500 error in turn): wrong number of arguments(given 2, expected 1) for will_paginate.
change the .paginate function parameters to be(:page => params[:page], :per_page => 11) as mentioned in the will_paginate documentation it still throws the same error. if i delete the per_page option it also still throws the same given 2 expected 1 error. i've also updated will-paginate and still get the same error

method "where" does not work when switched from will_paginate to pagy gem in rails

My will_paginate code in controller:
#posts = Post.paginate(page: params[:page], per_page: 100).order('created_at DESC')
My pagy code that replaced it:
#pagy, #posts = pagy_countless(Post.order('created_at DESC'), items:5, link_extra: 'class="" style="color:#222222; margin:3px;"')
My view where the problem is:
<% #posts.where(user_id: current_user.friends).each do |post| %>
The error message:
undefined method `where' for #<Array:0x00007f94329d1f70>
Did you mean? when
What am I doing wrong? The previous will_paginate implementation worked in terms of showing all the posts of user's friends. I'm lost as to what changed in switching to pagy.
UPDATE:
So for the moment, I've solved this by moving the "where..." logic to controller. So:
#pagy, #posts = pagy_countless(Post.where(user_id: current_user.friends).order('created_at DESC'), items:5, link_extra: 'class="" style="color:#222222; margin:3px;"')
And now it works as before. But I'm still confused as to why I had to do this.
Be aware pagy_countless returns an array of items, instead of an ActiveRecord collection. That's why you can't use ActiveRecord methods on #posts (like where).
Follow my link to see that collection is transformed into array using to_a and then it is returned as second argument of pagy_countless: https://github.com/ddnexus/pagy/blob/bd88866ad6001ae1ef6ce63080d36ecff7bc5603/lib/pagy/extras/countless.rb#L29
Two comments:
1. You must use ActiveRecord filters before calling pagy_countless on your collection (eg: where clauses)
2. If you need to filter records after pagination (which does not make sense in most of the cases), you must use Array methods like select of reject as following #posts.select { |record| record.user.in?(current_user.friends) }

Will_paginate in Dynamic pages as "search"

I'm having trouble with will_paginate. It works perfectly with static pages but not in dynamic pages. In my controller I have:
def search
#prods = Prods.find_all_by_producer(params[:producer])
#items = #prods.paginate(:page => params[:page], :per_page => 10)
end
In my view:
<%= will_paginate #items %>
The first 10 items (the first page) are well displayed but when I try to navigate to next pages, I have:
undefined method `paginate' for nil:NilClass
Parameters : {"page"=>"2","locale"=>nil}
I understand the issue, there is no params[:producer] when it calls the second page so #prods returns nil. But how to do that, any ideas?
Add the #prods as param like this:
{:producer=>#producer} %>
Source: http://www.cowboycoded.com/2009/09/08/appending-parameters-on-a-will_paginate-link/

Error with Kaminari pagination

I would like to paginate my objects with the Kaminari pagination gem. I have this line in my controller:
#products = Product.order("id").find_all_by_id(params[:id])
That line in my view:
<%= paginate #products %>
And that line in my model:
paginates_per 20
When I open my page where my objects are supposed to be listed, I have this error message :
undefined method `current_page' for #<Array:0x2964690>
The exception is raised at my <%= paginate #products %> line.
I have already made a pagination for another project and it was working really great. Could someone help me please ?
Thank you !
Edit:
The problem is that find_all_by_* returns an array, not an ActiveRecord::Relation.
You can do something like this instead
#products = Product.order("id").where("id IN (?)", params[:id])
Also, you should probably have a .page(params[:page]) in there.

Rails 3 + lazy loading + Kaminari for pagination + HAML

I would like to use the kaminari gem to paginate over search results. Since the gem does not "pollute" ActiveRecord::Base and Array, kaminari is actually my preferred way to go (from an architectural point of view). Unfortunately there is Rails 3 and its lazy loading concept that makes things a little bit confusing (at least at my scenario).
In my HAML-Template I would like to list all of my search results. When the result set is empty, I want to display a message telling the user that no results have been found. In the past I could do the following:
- unless #results.empty?
... search results ...
- else
... no results found ...
= paginate #results
Since .empty? does not force loading this does obviously no longer work in Rails 3. Jep, I could use .all in my Query to force loading. Unfortunately .all returns an Array and kaminari's paginate View helper does not work with Arrays (the right philosophy imho). I am curious how you would handle this kind of situation. Any best practices? All of my attempts ended in ugly constructions (like the one below). :/
To make things a little bit clearer:
My Controller action:
helper_method :keys
def groups
#results = []
if params[:query].present?
#results = Group.public
.where({:body.matches_any => keys} | {:subject.matches_any => keys})
.order('groups.updated_at DESC')
.page(params[:page])
.per(1)
end
respond_to do |format|
format.html
end
end
My "ugly" HAML-Template:
%h1= "Search results for \"#{params[:query]}\""
%br
%ol
- #results.each do |group|
%li
= link_to group.subject, group
%br
= group.body
%br
= group.created_at
- if #results.empty?
%div No results found ...
- else
=paginate(#results)
The problem here: it creates an ol-tag although no results have been found.
Any Ideas?
Thanks in advance!
works for me:
- if #applications.present?
%ul
- #applications.each do |application|
%li= application.name
%p= paginate #applications
- else
%p No results found ...
with kaminari (0.12.3)

Resources