noizZze

Kaminari Tips and Tricks

Moving a Rails 3.0 project to Rails 3.1 can be surprisingly tricky and especially if you use Mongoid, embedded collections, pagination and AJAX updates.

Mongoid 2.0.2 dropped own pagination and now fully relying on third-party tools. That’s a great idea and modularisation effort. However, now there’s a dilemma about what to use. I chose Kaminari for its up-to-date state and overall simplicity. I’d like to show a tricky part of making it all work.

Mongoid doesn’t let you operate freely on embedded collections and so doing this won’t work if images are embedded:

@user.images.desc(:created_at).page(params[:page]).per(10)

You can throw the sorting at the end of the line and it will (sort of) work, but there will always be just one page:

@user.images.page(params[:page]).per(10).desc(:created_at)

What I ended up doing is this:

Kaminari.paginate_array(@user.images.desc(:created_at).to_a).page(params[:page]).per(30)

Not very nice, but performance should be affected since its embedded collection and the documents are already in memory.

Now to Kaminari and AJAX. When you make an AJAX call, Rails 3 sets the format to :json, and so everyone knows what the client side expects. What I usually do when I need to update the paginated view is this:

render :json => {                                                    
  :pagination => render_to_string(:partial => 'images_pagination'),
  :images     => render_to_string(:partial => 'image', :collection => @images)
}

The problem with this is that Kaminari doesn’t have the renderer of pagination for the :json format and so it errors out. There are hacks to make templates “think” they have some desired format, but I found that the easiest (and the least ugly) solution is to append .html to the template name and instruct it about the format. As the result we have:

:pagination => render_to_string(:partial => 'images_pagination.html')

Comments