I am using plugin Kaminari for pagination. I am Ajaxifing my application and I encountered a problem. I have a form with paginated data plus form for filtering data (both via Ajax). At start pagination works good, and the url's for particular pages are '/admin/rooms?page=X'. After ajax filtering those url's change for '/admin/rooms/filter?page=X'. I can specify the action to trigger when paginating by:
<%= paginate @rooms, :params => {:controller => 'rooms', :action => 'index'}, :remote => true %>
but then variable @rooms gets resetted in index and I paginate unfiltered data again.
Any ideas how could I fix it?
Here's some code
rooms_controller.rb:
class Admin::RoomsController < AdminController
def index
@rooms = Room.all
@rooms = Kaminari.paginate_array(@rooms).page(params[:page]).per(5)
@filter_values = [['Room number', 'room_number'], ['Person count', 'person_count'], ['Room class', 'room_class']]
end
def filter
case params[:filter_by]
when 'room_number'
@rooms = Room.find(:all, :conditions => ["CAST(room_number AS VARCHAR) LIKE ?", "#{params[:filter_value]}%"])
when 'person_count'
@rooms = Room.find(:all, :conditions => ["person_count LIKE ?", "#{params[:filter_value]}%"])
else
@rooms = Room.joins(:room_class).where("lower(class_name) LIKE '#{params[:filter_value]}%'")
end
@rooms = Kaminari.paginate_array(@rooms).page(params[:page]).per(5)
respond_to do |format|
format.html { redirect_to admin_rooms_path }
format.js
end
end
index.html.erb:
<%= label_tag 'Filter: ' %>
<%= form_tag(filter_admin_rooms_path, :remote => true) do %>
<%= select_tag :filter_by, options_for_select(@filter_values) %>
<%= text_field_tag :filter_value %>
<%= submit_tag 'Filter', :disable_with => 'Filtering..' %>
<% end %>
...
<div id="rooms_list">
<%= render 'admin/rooms/shared/rooms_list' %>
</div>
_rooms_list.html.erb:
<div id="paginator">
<%= paginate @rooms, :remote => true %>
</div>
<table class="table_listing" style="width: 60%">
...
</table>
Problem solved by passing parameters again to index and forcing paginate to route to 'rooms#index', not the current page (not visible cause of Ajax though).
_rooms_list.html.erb:
<%= paginate @rooms, :params => {:controller => 'rooms', :action => 'index'}, :remote => true %>
Parametrs are passed to index by GET from the present params variable.
rooms_controller.rb:
def index
if params[:filter_value].nil?
@rooms = Room.all
else
@rooms = test_filter(params[:filter_value])
end
@rooms = Kaminari.paginate_array(@rooms).page(params[:page]).per(5)
@errors = flash[:errors] || []
@filter_values = [['Room number', 'room_number'], ['Person count', 'person_count'], ['Room class', 'room_class']]
end
def filter
case params[:filter_by]
when 'room_number'
@rooms = Room.find(:all, :conditions => ["CAST(room_number AS VARCHAR) LIKE ?", "#{params[:filter_value]}%"])
when 'person_count'
@rooms = Room.find(:all, :conditions => ["person_count LIKE ?", "#{params[:filter_value]}%"])
else
@rooms = Room.joins(:room_class).where("lower(class_name) LIKE '#{params[:filter_value]}%'")
end
@rooms = Kaminari.paginate_array(@rooms).page(params[:page]).per(5)
params[:authenticity_token] = nil
params[:commit] = nil
respond_to do |format|
format.html { redirect_to admin_rooms_path }
format.js
end
end
def test_filter(val)
rooms = Room.find(:all, :conditions => ["CAST(room_number AS VARCHAR) LIKE ?", "#{val}%"])
rooms
end
test_filter is to remove/rename of course. I nil some parameter that I think shouldn't be passed in params to the next page when paginate.