hobo_will_paginate 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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