Question

I'm trying to get will paginate to link to my nested route instead of the regular posts variable. I know I'm supposed to pass some params to paginate but I don't know how to pass them.

Basically there is an array stored in @posts and the other param paginate has access to is category_id.

The nested route is /category/1/posts but hitting next and previous on will paginate returns a url like this posts?page=1&category_id=7.

 <%= will_paginate @most_recent_posts "What do I do here?" %>

This is the result of Yannis's answer:

In your controller you can do:

@posts = @category.posts.paginate

And in your view:

<%= will_paginate(@post) %>

Doing this comes up with the following URL

posts?page=2&post_category_id=athlete_management

routes.rb #there are more routes but these are the relevant ones

map.resources :posts
map.resources :post_categories, :has_many => :posts

solution

 map.resources :post_categories do |post_category|
   post_category.resources :posts
  end
  map.resources :posts 

Had to declare the resource after the block

Thanks stephen!

Was it helpful?

Solution

Parachuting in here on this old question because I encountered the same issue.

I had pretty much exactly the same problem. I followed the responders' advice that something funky was going on with the routes. I dug into the routes and found (translated to suit your situation):

resources :posts
resources :categories do
  resources :posts
end

This made it so that calling category_posts_path returned (as expected) /category/1/posts.

However, it's of pivotal importance to realize that will_paginate calls something that resembles url_for, which works "backwards" from the routes to find the first route that matches the parameters.

Since resources :posts appears above the nested route, it sees that that one satisfies the requirements and just inserts category_id=1 was a query string.

The reason it worked "out of the box" for everyone else was because they didn't have the nested resource separately listed as a standalone resource.

Remove that and you should be fine!

OTHER TIPS

In your controller you can do:

@posts = @category.posts.paginate

And in your view:

<%= will_paginate(@post) %>

Okay, so it's not clear from the question exactly, but I'm assuming that you are trying to go from a root-level URL like /posts into pages for specific categories like /category/1/posts.

The reason I assume this is because I have nested routes (in a namespace even) where will_paginate works fine without any special params. If that is not the case then there is probably something else funky going on with your routes and more information will be needed to debug.

However I can at least explain how will_paginate works. When it's generating the page URLs it calls url_for with existing params plus the specific page needed. Therefore, if you already have a bunch of params set, it should preserve them, including ones that are part of the path itself. Fortunately it also allows you to pass additional params to merge in with the (surprise!) :params parameter to will_paginate.

Now assuming you have the nested routes set up properly, /category/1/posts can be generated by:

url_for(:controller => 'posts', 
        :category_id => '1')

But if you are on the page /posts then the params will only be:

{:controller => 'posts'}

So you need to pass the category_id to will_paginate like so:

<%= will_paginate @posts, :params => {:category_id => @posts.first.category_id} %>

If this doesn't work, then I suspect something wrong with your routes. Try putting a debug statement in the template and calling url_for with different permutations of the params. Remember that the route definition order matters and could be creating conflicts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top