I know the standard pagination solution is:
Sunspot.search(Model) do
keywords "123"
paginate :per_page => 10
end
But what I need is:
#s = Sunspot.search(Model) do
keywords "123"
end
magic_paginate(#s.results, :per_page => 10)
how to implement magic_paginate? And if I do that, the pagination still lazy-load(i.e. dont access 11th record through DB when I'm at page 1)?
it is possible with kaminari gem
Kaminari.paginate_array(#search.results).page((params[:page] rescue 1))
Related
I recently got the will_paginate gem installed and it works great, but I would like it to work with the setup I currently have. Right now I show all feeds (or posts) on the same page, but they are sorted after how many people clicked on that page:
controller.rb
#t = Time.now
#h1 = #t - 1.hour
#feeds = Feed.find(:all, :order => "created_at DESC").sort { |p1, p2| p2.impressionist_count(:filter=>:all, :start_date=>#h1) <=> p1.impressionist_count(:filter=>:all, :start_date=>#h1)}
Now... I tested the paginate gem and it works fine if I do this in the controller:
controller.rb
#feeds = Feed.paginate(:per_page => 10, :page => params[:page], :order => "created_at DESC")
So I thought 1+1=2 and tried to combine the two by doing:
controller.rb
#feeds = Feed.paginate(:per_page => 10, :page=>params[:page], :order => "created_at DESC").sort { |p1, p2| p2.impressionist_count(:filter=>:all, :start_date=>#h1) <=> p1.impressionist_count(:filter=>:all, :start_date=>#h1)}
I'm not able to sort my posts and paginate them. I get an error when I try to load the page:
undefined method `total_pages' for #
I would like this to work, it would be pretty sweet :). However, if it does not work, is there any other way of doing this?
Thanks in advance!
It's because will_paginate works by default only on ActiveRecord relationships. Once you use the sort, it's converted to an array. If you want will_paginate to work with an array, you'll need to require support for it in your controller.
require 'will_paginate/array'
def search
#location = Location.find(params[:location_id])
start_date = DateTime.strptime(params[:start_date], "%m-%d-%Y")
end_date = DateTime.strptime(params[:end_date], "%m-%d-%Y")
#songs = #location.songs.find(:all, :conditions => {:play_date => start_date..end_date}).paginate(:page => params[:page], :per_page => 40)
render 'show'
end
Here is my error
undefined method `paginate' for #<Array:0x007fb00e49e6c8>
all works if i remove the will_paginate but i need it...any ideas or is there a better way to write this controller
Try writing
#songs = #location.songs.where(:play_date => start_date..end_date).paginate(:page => params[:page], :per_page => 40)
The difference? where returns an ActiveRelation object, while find retrieves all the matching objects in an array.
Hope this helps.
NoMethodError: undefined method `paginate' for []:Array
My will_paninate works perfectly but above error jumped out after upgrading to version 3.0.0.
Add following require will solve the issue:
require 'will_paginate/array'
Check out this post for the backward compatibility of will_paginate 3.0.
The will_paginate documentation states that combining .paginate with .find is not the way to go, because .find will load everything from your DB before .paginate has a chance to restrict the fetch.
I've successfully installed Sunspot for my Ruby On Rails 3 project, but I can't seem to find a way to get the total hits for a search query.
this is my search request
#search = Sunspot.search(Job) do
fulltext params[:job]
paginate(:page => params[:offset], :per_page => 25)
end
It works well except I need to get total number of real hits, not the total results returned (in this case 25 because of :per_page => 25)
In other words, I want to be able to display: Showing 1 to 25 out of 883 jobs found
Any help would be appreciated!
thanks
The method total works here.
query_results = Sunspot.search(Recipe) do
keywords(params[:qs])
paginate(:page=>params[:page], :per_page=>30)
end
#search_results = query_result.results
#search_total = #search_results.total
Or, in your view, total_entries works on the results object.
%div
Your search for
= params[:qs]
returned
= pluralize(#search_results.total_entries, 'result')
Never used Sunspot, but have you tried this in your view:
Showing #{#search.hits.page} to #{#search.hits.per_page} out of #{#search.total} jobs found
I'm using ruby on rails 2.3.8 and will_paginate plugin.
I've just noticed that if I write something like this:
Announcement.paginate :page => params[:page], :per_page => 10, :conditions => some_condition
it will work.
But, if I write something like this:
announcements = Announcement.all :conditions => some_condition
#ann = announcements.paginate :page => params[:page], :per_page => 10
it won't recognize conditions.
EDIT:
I've developed a Search functionality and, due to a Sort functionality I had to implement, I had to put the search feat inside a model's method to call it from the controller every time I need either to search or sort by some field.
So, my model's methods look like this:
def self.search_by_relevance(words)
conditions = get_search_conditions(words)
Announcement.published.descend_by_featured.order_by_rate :conditions => conditions
end
where "published" and "order_by_rate" are named scopes and "descend_by_feature" belongs to "searchlogic" gem.
def self.get_search_conditions(words)
unless words.empty? or words.nil?
conditions = ''
words.each do |word|
if conditions.nil? or conditions.empty?
conditions = '(title like "%' + word + '%" or description like "%' + word + '%")'
else
conditions += ' and (title like "%' + word + '%" or description like "%' + word + '%")'
end
end
conditions
end
end
My controller's action looks like this:
def search
#announcements = Announcement.search_by_relevance(params[:txtSearch].to_s.split).paginate :page => params[:page], :per_page => 10 unless params[:txtSearch].nil? or params[:txtSearch].empty?
end
This syntax won't recognize the conditions specified in the model's method.
EDIT 2:
Thanks for the posts. Testing my code a little more I found out that if I write ".all" right after "order_by_rate" at this line Announcement.published.descend_by_featured.order_by_rate :conditions => conditions, in search_by_relevance method it will return the correct query, but will_paginate plugin will give me the following error(just if I add ".all"):
NoMethodError in AnnouncementsController#search
undefined method `to_i' for {:page=>nil, :per_page=>10}:Hash
D:/Proyectos/Cursometro/www/vendor/plugins/will_paginate/lib/will_paginate/collection.rb:15:in `initialize'
D:/Proyectos/Cursometro/www/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb:37:in `new'
D:/Proyectos/Cursometro/www/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb:37:in `paginate'
D:/Proyectos/Cursometro/www/app/controllers/announcements_controller.rb:276:in `search'
First of all, I don't understand why I have to add the ".all" to the query to work right, and second, I don't see why will_paginate won't work when I include ".all"(I also tried to add the following code but didn't work: :page => params[:page] || 1).
Also, if I include the ".all" syntax to the query, it will return:
SELECT * FROM announcements WHERE
((title like "%anuncio%" or
description like "%anuncio%")) AND
(announcements.state = 'published')
ORDER BY announcements.featured DESC
If I don't, it will return:
SELECT * FROM announcements WHERE
(announcements.state = 'published')
ORDER BY announcements.featured DESC
Do you see that no conditions are being included in the last one? This is causing the problem.
I don't know if this will work for you, but you can use paginate just like find, I mean, something like:
#announcements = Announcement.paginate_all_by_id params[:id],
:page => params[:page], :per_page => 10
Edit
#announcements is an array, right?
Well, I found this post and this other one that may help you.
Well, I kind of solve this by adding ".paginate"(instead of ".all") to my query in the model's method, passing by parameters the "page" and "per_page" values. It was not my idea to include pagination in models, but well...it's the solution I have for now. If you come up with a better one, I'll be glad to hear it :)
I apologize if this is a trivial question or my understanding of rails is weak.
I have 2 actions in my controller, index and refine_data.
index fetches and displays all the data from a database table.
refine_data weeds out unwanted data using regex and returns a subset of the data.
Controller looks like:
def index
Result.paginate :per_page => 5, :page => params[:page], :order => 'created_at DESC'
end
def refine_data
results = Result.all
new_results = get_subset(results)
redirect_to :action => 'index'
end
I would like to redirect the refine_data action to the same view (index) with new_results.
As new_results are not from the database table (or model), how do I go about constructing my paginate?
As I wrote in my answer to Sort by ranking algorithm using will-paginate, it is possible to use a custom find method to order the data.
It could be used similar to filter out unwanted data, since you just need to return a set of data. By modifying the name of your refine_data to something like find_refined_data you can use
Result.paginate_refined_data :per_page => 5, :page => params[:page], :order => 'created_at DESC'
in your index method. (Of course you need to return a set of records instead redirect to the index action)
BTW you could also use the paginate_by_sql method, if you are able specify your filter as a SQL query. This is probably more efficient than grabbing all records and performing a regex on them. But more complex I guess.
I was not successful in getting will_paginate to work by creating my own find method.
I was almost successful but not quite.
Here's what I've tried:
In Controller:
def refine_data
Result.paginate_refined_data :per_page => 5, :page => params[:page], :order => 'created_at DESC', :exclude =>"somestring"
end
In Model:
def find_refined_data(args)
exclude_string = args[:exclude];
new_results = do_some_work_and_exclude_records(#results,exclude_string)
end
will_paginate had trouble with me passing an additional parameter :exclude which it did not understand.
The simplest solution for me was to create my own WillPaginate::Collection object.
So here's how mine works now:
#The method name does not cause will_paginate to intercept and try to do its magic.
def new_find_refined_data(args)
exclude_string = args[:exclude];
new_results = do_some_work_and_exclude_records(#results,exclude_string)
#entries = WillPaginate::Collection.create(1, args[:per_page]) do |pager|
# inject the result array into the paginated collection:
pager.replace(new_results)
unless pager.total_entries
# the pager didn't manage to guess the total count, do it manually
pager.total_entries = new_results.length
end
end
end
Hope this will help any of the guys facing the same problem:
I'm not sure about the other answers - you may well want to move that method into your model class.
But answering your actual question.
The way to show the same view as another action is not to redirect but use:
render :action => :index
Yet another alternative might be to create a named_scope for your refined result set.
Can you formulate your "get_subset" business logic into database-style commands?
If so you can reconstruct your finder as a named_scope (with those conditions)
eg:
named_scope :blue_things, :conditions => {:colour => 'blue'}
and then just call paginate on that:
Result.blue_things.paginate :per_page => 5, :page => params[:page]