{"id":161,"date":"2007-01-24T16:25:55","date_gmt":"2007-01-24T14:25:55","guid":{"rendered":"http:\/\/www.dotmana.com\/index.php\/?p=161"},"modified":"2007-01-24T16:25:55","modified_gmt":"2007-01-24T14:25:55","slug":"rails-paginator-et-has_many-associations","status":"publish","type":"post","link":"http:\/\/www.dotmana.com\/weblog\/2007\/01\/rails-paginator-et-has_many-associations\/","title":{"rendered":"Rails, Paginator et has_many associations"},"content":{"rendered":"<p>Par d\u00e9faut, le m\u00e9lange de ces 3 ingr\u00e9dients ne fonctionne pas sous Rails.<\/p>\n<p>La solution est l\u00e0 :<\/p>\n<blockquote><p>I dove into RoR Pagination yesterday (ActionController::Pagination), and while it\u2019s great for paginating all data in a model, it really sucks for paginating data from an activerecord association (and by really sucks I mean doesn\u2019t support).<\/p>\n<p>Here\u2019s the problem.  Say I have a user who has a collection of photos:<\/p>\n<pre><code>\r\nclass User < ActiveRecord::Base\r\nhas_many :photos, :conditions => 'photos.is_deleted = false', :order => 'photos.created_at DESC'\r\n\r\nend\r\n<\/code><\/pre>\n<p>I want to have the ability to feed the user\u2019s photos to the paginator.  Unfortunately, the <code>paginate<\/code> function simply takes a collection id, and will not accept a set of data (an association, in this case). So, if I want to paginate photos on a user, I have to do this:<\/p>\n<pre><code>\r\n@photo_pages, @photos = paginate :photos,\r\n:conditions => [\"photos.user_id=? AND is_deleted = false\", @user.id],\r\n:order => \"photos.created_at DESC\"\r\n<\/code><\/pre>\n<p>What a mess. Now i\u2019ve lost the benefits of my association, since I have to define the association as part of the pagination rules. Very suprised Rails handles things this way, as it seems to violate the basic DRY principles. Anyways, I only had to write code like this a few times to realize how much of a pain in the ass it is, and I created a \u201cpaginate_association\u201d method to help me out.<\/p>\n<pre><code>\r\ndef paginate_association(object, assoc_name, find_options = {}, per_page = 10)\r\npage = (params[:page] || 1).to_i\r\n\r\nitem_count = object.send(assoc_name.to_s + '_count')\r\noffset = (page-1)*per_page\r\n\r\n@items = object.send(assoc_name).find(:all, {:offset => offset, :limit => per_page}.merge(find_options))\r\n@item_pages = Paginator.new self, item_count, per_page, page\r\n\r\nreturn @item_pages, @items\r\nend\r\n<\/code><\/pre>\n<p>I added this to my ApplicationController (application.rb), and now I can paginate assocations til the cows come home.<\/p>\n<pre><code>\r\n@photo_pages, @photos = paginate_association @user, :photos, :order => 'created_at'\r\n<\/code><\/pre>\n<p>This helper uses the Rails Pagination stuff, so you can easily use <code>paginate<\/code> or <code>paginate_association<\/code> with the same view. Great!<\/p>\n<p>You can also pass additional \u201cfind\u201d arguments, such as <code>:order, :include, :join<\/code>, etc\u2026<\/p>\n<p>Hopefully this is as useful for you as it\u2019s been for me!<\/p><\/blockquote>\n<p><a target=\"_blank\" href=\"http:\/\/www.meepr.com\/2006\/08\/02\/rails-pagination-with-associations\/\">source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Par d\u00e9faut, le m\u00e9lange de ces 3 ingr\u00e9dients ne fonctionne pas sous Rails. La solution est l\u00e0 : I dove into RoR Pagination yesterday (ActionController::Pagination), and while it\u2019s great for paginating all data in a model, it really sucks for &hellip; <a href=\"http:\/\/www.dotmana.com\/weblog\/2007\/01\/rails-paginator-et-has_many-associations\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-161","post","type-post","status-publish","format-standard","hentry","category-ruby-on-rails"],"_links":{"self":[{"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/posts\/161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/comments?post=161"}],"version-history":[{"count":0,"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/posts\/161\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/media?parent=161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/categories?post=161"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.dotmana.com\/weblog\/wp-json\/wp\/v2\/tags?post=161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}