Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make helpers work without count #944

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,6 @@ Just add `.without_count` to your paginated object:
User.page(3).without_count
```

In your view file, you can only use simple helpers like the following instead of the full-featured `paginate` helper:

```erb
<%= link_to_prev_page @users, 'Previous Page' %>
<%= link_to_next_page @users, 'Next Page' %>
```


## Paginating a Generic Array object

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def total_count(column_name = :all, _options = nil) #:nodoc:
def without_count
extend ::Kaminari::PaginatableWithoutCount
end

def without_count?
false
end
end

# A module that makes AR::Relation paginatable without having to cast another SELECT COUNT query
Expand Down Expand Up @@ -87,8 +91,11 @@ def out_of_range?

# Force to raise an exception if #total_count is called explicitly.
def total_count
raise "This scope is marked as a non-count paginable scope and can't be used in combination " \
"with `#paginate' or `#page_entries_info'. Use #link_to_next_page or #link_to_previous_page instead."
raise 'This scope is marked as a non-count paginable scope.'
end

def without_count?
true
end
end
end
2 changes: 2 additions & 0 deletions kaminari-core/config/locales/kaminari.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ en:
other: "Displaying <b>all %{count}</b> %{entry_name}"
more_pages:
display_entries: "Displaying %{entry_name} <b>%{first}&nbsp;-&nbsp;%{last}</b> of <b>%{total}</b> in total"
without_count:
display_entries: "Displaying %{entry_name} <b>%{first}&nbsp;-&nbsp;%{last}</b>"
18 changes: 14 additions & 4 deletions kaminari-core/lib/kaminari/helpers/helper_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,13 @@ module HelperMethods
# * <tt>:template</tt> - Specify a custom template renderer for rendering the Paginator (receiver by default)
# * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
def paginate(scope, paginator_class: Kaminari::Helpers::Paginator, template: nil, **options)
options[:total_pages] ||= scope.total_pages
if scope.without_count?
options[:without_count] = true
options[:total_pages] = scope.last_page? ? scope.current_page : scope.current_page + 1
else
options[:total_pages] ||= scope.total_pages
end

options.reverse_merge! current_page: scope.current_page, per_page: scope.limit_value, remote: false

paginator = paginator_class.new (template || self), options
Expand Down Expand Up @@ -200,13 +206,17 @@ def page_entries_info(collection, entry_name: nil)
collection.entry_name(count: collection.size).downcase
end

if collection.total_pages < 2
t('helpers.page_entries_info.one_page.display_entries', entry_name: entry_name, count: collection.total_count)
if collection.first_page? && !collection.next_page
t('helpers.page_entries_info.one_page.display_entries', entry_name: entry_name, count: collection.size)
else
from = collection.offset_value + 1
to = collection.offset_value + collection.size

t('helpers.page_entries_info.more_pages.display_entries', entry_name: entry_name, first: from, last: to, total: collection.total_count)
if collection.without_count?
t('helpers.page_entries_info.without_count.display_entries', entry_name: entry_name, first: from, last: to)
else
t('helpers.page_entries_info.more_pages.display_entries', entry_name: entry_name, first: from, last: to, total: collection.total_count)
end
end.html_safe
end

Expand Down
6 changes: 5 additions & 1 deletion kaminari-core/lib/kaminari/helpers/paginator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ def initialize(template, window: nil, outer_window: Kaminari.config.outer_window
else
ActiveSupport::SafeBuffer.new
end

@render_without_count = true
end

# render given block as a view template
def render(&block)
instance_eval(&block) if @options[:total_pages] > 1
instance_eval(&block) if @options[:total_pages] > 1 || @options[:without_count]

# This allows for showing fall-back HTML when there's only one page:
#
Expand All @@ -49,6 +51,8 @@ def each_relevant_page
alias each_page each_relevant_page

def relevant_pages(options)
return [] if @options[:without_count]

left_window_plus_one = [*1..options[:left] + 1]
right_window_plus_one = [*options[:total_pages] - options[:right]..options[:total_pages]]
inside_window_plus_each_sides = [*options[:current_page] - options[:window] - 1..options[:current_page] + options[:window] + 1]
Expand Down
7 changes: 7 additions & 0 deletions kaminari-core/lib/kaminari/helpers/tags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ def initialize(template, params: {}, param_name: nil, theme: nil, views_prefix:
@params = @params.with_indifferent_access
@params.except!(*PARAM_KEY_BLACKLIST)
@params.merge! params
@render_without_count = false
end

def to_s(locals = {}) #:nodoc:
return '' if @options[:without_count] && !@render_without_count

formats = (@template.respond_to?(:formats) ? @template.formats : Array(@template.params[:format])) + [:html]
@template.render partial: partial_path, locals: @options.merge(locals), formats: formats
end
Expand Down Expand Up @@ -128,6 +131,8 @@ def initialize(template, params: {}, param_name: nil, theme: nil, views_prefix:
end

super(template, params: params, param_name: param_name, theme: theme, views_prefix: views_prefix, **options)

@render_without_count = true
end

def page #:nodoc:
Expand All @@ -149,6 +154,8 @@ def initialize(template, params: {}, param_name: nil, theme: nil, views_prefix:
end

super(template, params: params, param_name: param_name, theme: theme, views_prefix: views_prefix, **options)

@render_without_count = true
end

def page #:nodoc:
Expand Down
113 changes: 113 additions & 0 deletions kaminari-core/test/helpers/action_view_extension_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ def to_s
assert_not_match(/Last/, html)
assert_not_match(/Next/, html)
end

test 'scope without count' do
users = User.page(7).without_count

html = view.paginate users, params: {controller: 'users', action: 'index'}
assert_match(/<a [^>]*>&lsaquo; Prev<\/a>/, html)
assert_match(/<a [^>]*>Next &rsaquo;<\/a>/, html)
assert_not_match(/First/, html)
assert_not_match(/Last/, html)
end
end

sub_test_case '#link_to_previous_page' do
Expand Down Expand Up @@ -472,6 +482,109 @@ def total_count
end
end

sub_test_case 'on a scope without count' do
sub_test_case 'having no entries' do
test 'with default entry name' do
users = User.page(1).per(25).without_count
assert_equal 'No users found', view.page_entries_info(users)
end

test 'setting the entry name option to "member"' do
users = User.page(1).per(25).without_count
assert_equal 'No members found', view.page_entries_info(users, entry_name: 'member')
end
end

sub_test_case 'having 1 entry' do
setup do
User.create! name: 'user1'
end

test 'with default entry name' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying <b>1</b> user', view.page_entries_info(users)
end

test 'setting the entry name option to "member"' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying <b>1</b> member', view.page_entries_info(users, entry_name: 'member')
end
end

sub_test_case 'having more than 1 but less than a page of entries' do
setup do
10.times {|i| User.create! name: "user#{i}"}
end

test 'with default entry name' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying <b>all 10</b> users', view.page_entries_info(users)
end

test 'setting the entry name option to "member"' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying <b>all 10</b> members', view.page_entries_info(users, entry_name: 'member')
end
end

sub_test_case 'having more than one page of entries' do
setup do
50.times {|i| User.create! name: "user#{i}"}
end

sub_test_case 'the first page' do
test 'with default entry name' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying users <b>1&nbsp;-&nbsp;25</b>', view.page_entries_info(users)
end

test 'setting the entry name option to "member"' do
users = User.page(1).per(25).without_count
assert_equal 'Displaying members <b>1&nbsp;-&nbsp;25</b>', view.page_entries_info(users, entry_name: 'member')
end
end

sub_test_case 'the next page' do
test 'with default entry name' do
users = User.page(2).per(25).without_count
assert_equal 'Displaying users <b>26&nbsp;-&nbsp;50</b>', view.page_entries_info(users)
end

test 'setting the entry name option to "member"' do
users = User.page(2).per(25).without_count
assert_equal 'Displaying members <b>26&nbsp;-&nbsp;50</b>', view.page_entries_info(users, entry_name: 'member')
end
end

sub_test_case 'the last page' do
test 'with default entry name' do
begin
User.max_pages 4
users = User.page(4).per(10).without_count

assert_equal 'Displaying users <b>31&nbsp;-&nbsp;40</b>', view.page_entries_info(users)
ensure
User.max_pages nil
end
end
end

test 'it accepts a decorated object' do
page_info_presenter = Class.new(SimpleDelegator) do
include ActionView::Helpers::NumberHelper

def total_count
number_with_delimiter(1_000)
end
end

users = page_info_presenter.new(User.page(1).per(25).without_count)

assert_equal 'Displaying users <b>1&nbsp;-&nbsp;25</b>', view.page_entries_info(users)
end
end
end

test 'on a PaginatableArray' do
numbers = Kaminari.paginate_array(%w{one two three}).page(1)

Expand Down