# = Pager # # code: gmosx # # (c) 2004 Navel, all rights reserved. # $Id: pager.rb 71 2004-10-18 10:50:22Z gmosx $ module N; module UI # === Design: # # The new version is carefully designed for scaleability. It stores # only the items for one page. # The name parameter is needed, multiple pagers can coexist in # a single page. Unlike the v1/v2 pagers this pager leverages the # SQL LIMIT option to optimize database interaction. # # The pager does not extend Array (it includes an Array instead) to # avoid a concat() in the initialization step. # # TODO: # - Extend from array? (would be more elegant) # # === Example: # # INVESTIGATE: # mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name # -> WHERE id > 100 LIMIT 10; # mysql> SELECT FOUND_ROWS(); # class Pager < Array attr_accessor :name, :idx, :page, :page_count # total count of items attr_accessor :total_count # page items attr_accessor :page_items # read needed variables from the request. attr_accessor :request def initialize(name, request, items_per_page, items = nil) raise "items_per_page should be > 0" unless items_per_page > 0 @request, @name = request, name @page = request.get("__pg#{@name}", 1) @items_per_page = items_per_page @start_idx = (@page - 1) * items_per_page if items set(items.size()) # gmosx, FIXME: not exactly what i want! items.slice!(@start_idx, @items_per_page) end end def set(total_count) @total_count = total_count @page_count = (@total_count.to_f() / @items_per_page).ceil() end def first_page return 1 end def last_page return @page_count end def previous_page return [@page - 1, 1].max() end def next_page return [@page + 1, @page_count].min() end # Iterator # def each(&block) @page_items.each(&block) end # Iterator # Returns 1-based index. # def each_with_index idx = @start_idx for item in @page_items yield(idx + 1, item) idx += 1 end end def empty? return @items.empty? end def size return @items.size() end # Returns the range of the current page. # def page_range s = @idx e = [@idx + @items_per_page - 1, all_total_count].min return [s, e] end # Override if needed. # def nav_range # effective range = 10 pages. s = [@page - 5, 1].max() e = [@page + 9, @page_count].min() d = 9 - (e - s) e += d if d < 0 return (s..e) end # Override this method in your application # if needed. # TODO: better markup. # def navigation nav = "" unless @page == first_page() nav << %{
Αρχή
} end unless @page == last_page() nav << %{
Τέλος
} end nav << %{} return nav end # Create an appropriate SQL limit clause. # Returns postgres/mysql compatible limit. # def sql_limit if @start_idx > 0 return "LIMIT #{@items_per_page} OFFSET #{@start_idx}" else # gmosx: perhaps this is optimized ? naaaaaah... return "LIMIT #{@items_per_page}" end end # ------------------------------------------------------------------ # Generate the target URI. # def target_uri(page) params = {"__pg#{@name}" => page} return N::UriUtils.update_query_string(@request.uri, params) end private :target_uri end end; end # module