hobo_will_paginate 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +18 -0
  3. data/README.md +61 -0
  4. data/Rakefile +25 -0
  5. data/lib/will_paginate.rb +25 -0
  6. data/lib/will_paginate/active_record.rb +216 -0
  7. data/lib/will_paginate/array.rb +57 -0
  8. data/lib/will_paginate/collection.rb +149 -0
  9. data/lib/will_paginate/core_ext.rb +30 -0
  10. data/lib/will_paginate/data_mapper.rb +95 -0
  11. data/lib/will_paginate/deprecation.rb +55 -0
  12. data/lib/will_paginate/i18n.rb +22 -0
  13. data/lib/will_paginate/locale/en.yml +33 -0
  14. data/lib/will_paginate/page_number.rb +57 -0
  15. data/lib/will_paginate/per_page.rb +27 -0
  16. data/lib/will_paginate/railtie.rb +68 -0
  17. data/lib/will_paginate/sequel.rb +39 -0
  18. data/lib/will_paginate/version.rb +9 -0
  19. data/lib/will_paginate/view_helpers.rb +161 -0
  20. data/lib/will_paginate/view_helpers/action_view.rb +148 -0
  21. data/lib/will_paginate/view_helpers/link_renderer.rb +132 -0
  22. data/lib/will_paginate/view_helpers/link_renderer_base.rb +77 -0
  23. data/lib/will_paginate/view_helpers/merb.rb +26 -0
  24. data/lib/will_paginate/view_helpers/sinatra.rb +41 -0
  25. data/spec/ci.rb +29 -0
  26. data/spec/collection_spec.rb +139 -0
  27. data/spec/console +12 -0
  28. data/spec/console_fixtures.rb +28 -0
  29. data/spec/database.yml +22 -0
  30. data/spec/finders/active_record_spec.rb +543 -0
  31. data/spec/finders/activerecord_test_connector.rb +113 -0
  32. data/spec/finders/data_mapper_spec.rb +103 -0
  33. data/spec/finders/data_mapper_test_connector.rb +54 -0
  34. data/spec/finders/sequel_spec.rb +67 -0
  35. data/spec/finders/sequel_test_connector.rb +9 -0
  36. data/spec/fixtures/admin.rb +3 -0
  37. data/spec/fixtures/developer.rb +13 -0
  38. data/spec/fixtures/developers_projects.yml +13 -0
  39. data/spec/fixtures/project.rb +15 -0
  40. data/spec/fixtures/projects.yml +6 -0
  41. data/spec/fixtures/replies.yml +29 -0
  42. data/spec/fixtures/reply.rb +9 -0
  43. data/spec/fixtures/schema.rb +38 -0
  44. data/spec/fixtures/topic.rb +7 -0
  45. data/spec/fixtures/topics.yml +30 -0
  46. data/spec/fixtures/user.rb +2 -0
  47. data/spec/fixtures/users.yml +35 -0
  48. data/spec/page_number_spec.rb +65 -0
  49. data/spec/per_page_spec.rb +41 -0
  50. data/spec/spec_helper.rb +71 -0
  51. data/spec/view_helpers/action_view_spec.rb +423 -0
  52. data/spec/view_helpers/base_spec.rb +130 -0
  53. data/spec/view_helpers/link_renderer_base_spec.rb +87 -0
  54. data/spec/view_helpers/view_example_group.rb +114 -0
  55. metadata +104 -0
@@ -0,0 +1,30 @@
1
+ require 'set'
2
+
3
+ # copied from ActiveSupport so we don't depend on it
4
+
5
+ unless Hash.method_defined? :except
6
+ Hash.class_eval do
7
+ # Returns a new hash without the given keys.
8
+ def except(*keys)
9
+ rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
10
+ reject { |key,| rejected.include?(key) }
11
+ end
12
+
13
+ # Replaces the hash without only the given keys.
14
+ def except!(*keys)
15
+ replace(except(*keys))
16
+ end
17
+ end
18
+ end
19
+
20
+ unless String.method_defined? :underscore
21
+ String.class_eval do
22
+ def underscore
23
+ self.to_s.gsub(/::/, '/').
24
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
25
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
26
+ tr("-", "_").
27
+ downcase
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,95 @@
1
+ require 'dm-core'
2
+ require 'dm-aggregates'
3
+ require 'will_paginate/per_page'
4
+ require 'will_paginate/page_number'
5
+ require 'will_paginate/collection'
6
+
7
+ module WillPaginate
8
+ module DataMapper
9
+ module Pagination
10
+ def page(num)
11
+ pagenum = ::WillPaginate::PageNumber(num.nil? ? 1 : num)
12
+ per_page = query.limit || self.per_page
13
+ options = {:offset => pagenum.to_offset(per_page).to_i}
14
+ options[:limit] = per_page unless query.limit
15
+ col = new_collection(query.merge(options))
16
+ col.current_page = pagenum
17
+ col
18
+ end
19
+
20
+ def paginate(options)
21
+ options = options.dup
22
+ pagenum = options.fetch(:page) { raise ArgumentError, ":page parameter required" }
23
+ per_page = options.delete(:per_page) || self.per_page
24
+
25
+ options.delete(:page)
26
+ options[:limit] = per_page.to_i
27
+
28
+ all(options).page(pagenum)
29
+ end
30
+ end
31
+
32
+ module CollectionMethods
33
+ include WillPaginate::CollectionMethods
34
+
35
+ attr_accessor :current_page
36
+
37
+ def paginated?
38
+ !current_page.nil?
39
+ end
40
+
41
+ def per_page
42
+ query.limit || model.per_page
43
+ end
44
+
45
+ def offset
46
+ query.offset
47
+ end
48
+
49
+ def total_entries
50
+ @total_entries ||= begin
51
+ if loaded? and @array.size < per_page and (current_page == 1 or @array.size > 0)
52
+ offset + @array.size
53
+ else
54
+ # :reload prevents Collection.filter from being run, which
55
+ # would cause a stack overflow
56
+ clean_query = query.merge(:reload => true)
57
+ # seems like the only way
58
+ clean_query.instance_variable_set('@limit', nil)
59
+ clean_query.instance_variable_set('@offset', 0)
60
+ new_collection(clean_query).count
61
+ end
62
+ end
63
+ end
64
+
65
+ def to_a
66
+ if paginated?
67
+ ::WillPaginate::Collection.create(current_page, per_page) do |col|
68
+ col.replace super
69
+ col.total_entries ||= total_entries
70
+ end
71
+ else
72
+ super
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def new_collection(query, resources = nil)
79
+ col = super
80
+ col.current_page = self.current_page
81
+ col
82
+ end
83
+
84
+ def initialize_copy(original)
85
+ super
86
+ @total_entries = nil
87
+ end
88
+ end
89
+
90
+ ::DataMapper::Model.append_extensions PerPage
91
+ ::DataMapper::Model.append_extensions Pagination
92
+ ::DataMapper::Collection.send(:include, Pagination)
93
+ ::DataMapper::Collection.send(:include, CollectionMethods)
94
+ end
95
+ end
@@ -0,0 +1,55 @@
1
+ module WillPaginate::Deprecation
2
+ class << self
3
+ def warn(message, stack = caller)
4
+ offending_line = origin_of_call(stack)
5
+ full_message = "DEPRECATION WARNING: #{message} (called from #{offending_line})"
6
+ logger = rails_logger || Kernel
7
+ logger.warn full_message
8
+ end
9
+
10
+ private
11
+
12
+ def rails_logger
13
+ defined?(Rails) && Rails.logger
14
+ end
15
+
16
+ def origin_of_call(stack)
17
+ lib_root = File.expand_path('../../..', __FILE__)
18
+ stack.find { |line| line.index(lib_root) != 0 } || stack.first
19
+ end
20
+ end
21
+
22
+ class Hash < ::Hash
23
+ def initialize(values = {})
24
+ super()
25
+ update values
26
+ @deprecated = {}
27
+ end
28
+
29
+ def []=(key, value)
30
+ check_deprecated(key, value)
31
+ super
32
+ end
33
+
34
+ def deprecate_key(*keys)
35
+ message = block_given? ? Proc.new : keys.pop
36
+ Array(keys).each { |key| @deprecated[key] = message }
37
+ end
38
+
39
+ def merge(another)
40
+ to_hash.update(another)
41
+ end
42
+
43
+ def to_hash
44
+ ::Hash.new.update(self)
45
+ end
46
+
47
+ private
48
+
49
+ def check_deprecated(key, value)
50
+ if msg = @deprecated[key] and (!msg.respond_to?(:call) or (msg = msg.call(key, value)))
51
+ WillPaginate::Deprecation.warn(msg)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ module WillPaginate
2
+ module I18n
3
+ def self.locale_dir
4
+ File.expand_path('../locale', __FILE__)
5
+ end
6
+
7
+ def self.load_path
8
+ Dir["#{locale_dir}/*.{rb,yml}"]
9
+ end
10
+
11
+ def will_paginate_translate(keys, options = {})
12
+ if defined? ::I18n
13
+ defaults = Array(keys).dup
14
+ defaults << Proc.new if block_given?
15
+ ::I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => :will_paginate))
16
+ else
17
+ key = Array === keys ? keys.first : keys
18
+ yield key, options
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ en:
2
+ will_paginate:
3
+ previous_label: "&#8592; Previous"
4
+ next_label: "Next &#8594;"
5
+ page_gap: "&hellip;"
6
+
7
+ page_entries_info:
8
+ single_page:
9
+ zero: "No %{model} found"
10
+ one: "Displaying 1 %{model}"
11
+ other: "Displaying all %{count} %{model}"
12
+ single_page_html:
13
+ zero: "No %{model} found"
14
+ one: "Displaying <b>1</b> %{model}"
15
+ other: "Displaying <b>all&nbsp;%{count}</b> %{model}"
16
+
17
+ multi_page: "Displaying %{model} %{from} - %{to} of %{count} in total"
18
+ multi_page_html: "Displaying %{model} <b>%{from}&nbsp;-&nbsp;%{to}</b> of <b>%{count}</b> in total"
19
+
20
+ # models:
21
+ # entry:
22
+ # zero: entries
23
+ # one: entry
24
+ # few: entries
25
+ # other: entries
26
+
27
+ # line_item:
28
+ # page_entries_info:
29
+ # single_page:
30
+ # zero: "Your shopping cart is empty"
31
+ # one: "Displaying one item in your cart"
32
+ # other: "Displaying all %{count} items"
33
+ # multi_page: "Displaying items %{from} - %{to} of %{count} in total"
@@ -0,0 +1,57 @@
1
+ require 'delegate'
2
+ require 'forwardable'
3
+
4
+ module WillPaginate
5
+ # a module that page number exceptions are tagged with
6
+ module InvalidPage; end
7
+
8
+ # integer representing a page number
9
+ class PageNumber < DelegateClass(Integer)
10
+ # a value larger than this is not supported in SQL queries
11
+ BIGINT = 9223372036854775807
12
+
13
+ extend Forwardable
14
+
15
+ def initialize(value, name)
16
+ value = Integer(value)
17
+ if 'offset' == name ? (value < 0 or value > BIGINT) : value < 1
18
+ raise RangeError, "invalid #{name}: #{value.inspect}"
19
+ end
20
+ @name = name
21
+ super(value)
22
+ rescue ArgumentError, TypeError, RangeError => error
23
+ error.extend InvalidPage
24
+ raise error
25
+ end
26
+
27
+ alias_method :to_i, :__getobj__
28
+
29
+ def inspect
30
+ "#{@name} #{to_i}"
31
+ end
32
+
33
+ def to_offset(per_page)
34
+ PageNumber.new((to_i - 1) * per_page.to_i, 'offset')
35
+ end
36
+
37
+ def kind_of?(klass)
38
+ super || to_i.kind_of?(klass)
39
+ end
40
+ alias is_a? kind_of?
41
+ end
42
+
43
+ # Ultrahax: makes `Fixnum === current_page` checks pass
44
+ Numeric.extend Module.new {
45
+ def ===(obj)
46
+ obj.instance_of? PageNumber or super
47
+ end
48
+ }
49
+
50
+ # An idemptotent coercion method
51
+ def self.PageNumber(value, name = 'page')
52
+ case value
53
+ when PageNumber then value
54
+ else PageNumber.new(value, name)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,27 @@
1
+ module WillPaginate
2
+ module PerPage
3
+ def per_page
4
+ defined?(@per_page) ? @per_page : WillPaginate.per_page
5
+ end
6
+
7
+ def per_page=(limit)
8
+ @per_page = limit.to_i
9
+ end
10
+
11
+ def self.extended(base)
12
+ base.extend Inheritance if base.is_a? Class
13
+ end
14
+
15
+ module Inheritance
16
+ def inherited(subclass)
17
+ super
18
+ subclass.per_page = self.per_page
19
+ end
20
+ end
21
+ end
22
+
23
+ extend PerPage
24
+
25
+ # default number of items per page
26
+ self.per_page = 30
27
+ end
@@ -0,0 +1,68 @@
1
+ require 'will_paginate'
2
+ require 'will_paginate/page_number'
3
+ require 'will_paginate/collection'
4
+ require 'will_paginate/i18n'
5
+
6
+ module WillPaginate
7
+ class Railtie < Rails::Railtie
8
+ initializer "will_paginate" do |app|
9
+ ActiveSupport.on_load :active_record do
10
+ require 'will_paginate/active_record'
11
+ end
12
+
13
+ ActiveSupport.on_load :action_controller do
14
+ WillPaginate::Railtie.setup_actioncontroller
15
+ end
16
+
17
+ ActiveSupport.on_load :action_view do
18
+ require 'will_paginate/view_helpers/action_view'
19
+ end
20
+
21
+ self.class.add_locale_path config
22
+
23
+ # early access to ViewHelpers.pagination_options
24
+ require 'will_paginate/view_helpers'
25
+ end
26
+
27
+ def self.setup_actioncontroller
28
+ ( defined?(ActionDispatch::ExceptionWrapper) ?
29
+ ActionDispatch::ExceptionWrapper : ActionDispatch::ShowExceptions
30
+ ).send :include, ShowExceptionsPatch
31
+ ActionController::Base.extend ControllerRescuePatch
32
+ end
33
+
34
+ def self.add_locale_path(config)
35
+ config.i18n.railties_load_path.unshift(*WillPaginate::I18n.load_path)
36
+ end
37
+
38
+ # Extending the exception handler middleware so it properly detects
39
+ # WillPaginate::InvalidPage regardless of it being a tag module.
40
+ module ShowExceptionsPatch
41
+ extend ActiveSupport::Concern
42
+ included { alias_method_chain :status_code, :paginate }
43
+ def status_code_with_paginate(exception = @exception)
44
+ if exception.is_a?(WillPaginate::InvalidPage) or
45
+ (exception.respond_to?(:original_exception) &&
46
+ exception.original_exception.is_a?(WillPaginate::InvalidPage))
47
+ Rack::Utils.status_code(:not_found)
48
+ else
49
+ original_method = method(:status_code_without_paginate)
50
+ if original_method.arity != 0
51
+ original_method.call(exception)
52
+ else
53
+ original_method.call()
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ module ControllerRescuePatch
60
+ def rescue_from(*args, &block)
61
+ if idx = args.index(WillPaginate::InvalidPage)
62
+ args[idx] = args[idx].name
63
+ end
64
+ super(*args, &block)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ require 'sequel'
2
+ require 'sequel/extensions/pagination'
3
+ require 'will_paginate/collection'
4
+
5
+ module WillPaginate
6
+ # Sequel already supports pagination; we only need to make the
7
+ # resulting dataset look a bit more like WillPaginate::Collection
8
+ module SequelMethods
9
+ include WillPaginate::CollectionMethods
10
+
11
+ def total_pages
12
+ page_count
13
+ end
14
+
15
+ def per_page
16
+ page_size
17
+ end
18
+
19
+ def size
20
+ current_page_record_count
21
+ end
22
+ alias length size
23
+
24
+ def total_entries
25
+ pagination_record_count
26
+ end
27
+
28
+ def out_of_bounds?
29
+ current_page > total_pages
30
+ end
31
+
32
+ # Current offset of the paginated collection
33
+ def offset
34
+ (current_page - 1) * per_page
35
+ end
36
+ end
37
+
38
+ Sequel::Dataset::Pagination.send(:include, SequelMethods)
39
+ end
@@ -0,0 +1,9 @@
1
+ module WillPaginate #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 2
4
+ MINOR = 1
5
+ TINY = '0'
6
+
7
+ STRING = '2.1.0'
8
+ end
9
+ end