Reputation: 75
I'm struggling with a seemingly simple offset/limit pagination query in rails 3.
The class:
class Topic < ActiveRecord::Base
set_primary_key "thread_id"
set_table_name "threads"
belongs_to :forum_board
belongs_to :user
has_many :posts, :foreign_key => "thread_id", :dependent => :destroy
attr_accessible :board_id, :title, :modified_date, :status, :post_count, :user_id, :posts_attributes
accepts_nested_attributes_for :posts, :allow_destroy => :true
attr_accessor :board_title, :admin_mode, :orig_page_number, :page_number,
:per_page, :last_page, :ban_list
And the query is this:
Topic.includes(:posts, :user).where("threads.thread_id=? and messages.status=2", thread_id).order("messages.pdate").limit(per_page).offset(offset).first
The quandary is that whenever the offset>1, the results are coming back empty. So for example, limit=5, offset=5 (with 20 rows available) fails.
I'm also seeing the following SQL run ahead of the query on the child table, which in fact returns no results due to the DISTINCT clause:
SELECT DISTINCT `threads`.thread_id FROM `threads` LEFT OUTER JOIN `messages` ON `messages`.`thread_id` = `threads`.`thread_id` LEFT OUTER JOIN `users` ON `users`.`user_id` = `threads`.`user_id` WHERE (threads.thread_id='20367' and messages.status=2) ORDER BY messages.pdate LIMIT 1 OFFSET 5
I'm sure I've just made a mess of limit/offset here. Any help appreciated.
Upvotes: 1
Views: 7792
Reputation: 4428
I'm not 100% sure what's going wrong there as it looks right, but take a look at the Kaminari gem, either for the source or to actually use it.
It essentially handles pagination for you and makes it REALLY easy to use. In your example, with Kaminari you'd just do
Topic.page(1).per(5)
You can still add all of your conditions in as well, but it also comes with view helpers to setup pagination links.
But as I say, take a look through the gem source to see what it's doing and compare with yours, and it looks right. It might be that MySQL works like other DMBS's I've used, in that the limit and the offset don't work how you expect. By limiting the query to 5 results, you're expecting to get just 5 which is fine. If you then offset by 5, after you've limited it to 5 results, there are then no more results to offset by?
I could be COMPLETELY wrong there so I'd suggest looking at the kaminari code but just a hunch :)
Upvotes: 2