kaminari-activerecord 1.2.1 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6876071aa2d14ad868c0b30fe2d47478c6237c8d2e32f5e09ff2d6406d308f8c
4
- data.tar.gz: 9ab1589acaec71a5ad35eeb9f80b38d7d6abcfd4f9ee83a468ab9686e8bcb2e1
3
+ metadata.gz: eefaf1569dfa8c30cb89e8f713ef3662f377fe009f1f88e434d5fe5f2878b7b9
4
+ data.tar.gz: 77ce58b9c3b353cfa55d3cf2dd135000e482dae3c4468615bc6a16279ded7a2f
5
5
  SHA512:
6
- metadata.gz: dc82c0b5e7aa6292bdbe94474b1a7c532706a6d07886a7a44134e49d593102d21a052a29cbd8edf187b7b1a0e736a1638bdd92fcfa7fe3bc4a6b54b2fb73599f
7
- data.tar.gz: 7c6904976fdc124170c8b01294dacca2433e86895f60f7a1cabfccfd780cfac2f59263cd1777dc70cbf74e745939174b5ee29eee7df20909eca537b45172e001
6
+ metadata.gz: 1be89a8131bde20e066ceb017c6ca1f00538d8fb6b97c3beaa34c92a6d16db44bbff52e7caa652b801f7af5f5d17465d2b63f078ddfe5c045688b0c6ccbb81ef
7
+ data.tar.gz: e0343ad91043c04646639edd68bbb508ffd1b4395e5292a02eadeae2b1a48cfee069405e9962cc55a8188ee09e454f5443f5a73704e4081063f1c6ab6c6bce19
@@ -14,6 +14,13 @@ Gem::Specification.new do |spec|
14
14
  spec.description = 'kaminari-activerecord lets your Active Record models be paginatable'
15
15
  spec.homepage = 'https://github.com/kaminari/kaminari'
16
16
  spec.license = "MIT"
17
+
18
+ spec.metadata = {
19
+ 'changelog_uri' => 'https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md',
20
+ 'source_code_uri' => 'https://github.com/kaminari/kaminari/tree/master/kaminari-activerecord',
21
+ 'rubygems_mfa_required' => 'true'
22
+ }
23
+
17
24
  spec.required_ruby_version = '>= 2.0.0'
18
25
 
19
26
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -3,21 +3,32 @@
3
3
  require 'kaminari/activerecord/active_record_relation_methods'
4
4
 
5
5
  module Kaminari
6
+ # Extends the Relation returned by Model.page.
7
+ # Passing this module to `extending` rather than a block saves defining a new Module on each call.
8
+ module ActiveRecordPageScope
9
+ include Kaminari::PageScopeMethods
10
+ # included after PageScopeMethods so that it can override PageScopeMethods#limit_and_offset
11
+ include Kaminari::ActiveRecordRelationMethods
12
+ end
13
+
6
14
  module ActiveRecordModelExtension
7
15
  extend ActiveSupport::Concern
8
16
 
9
17
  included do
10
18
  include Kaminari::ConfigurationMethods
11
19
 
20
+ def self.paginated?
21
+ false
22
+ end
23
+
12
24
  # Fetch the values at the specified page number
13
25
  # Model.page(5)
14
26
  eval <<-RUBY, nil, __FILE__, __LINE__ + 1
15
27
  def self.#{Kaminari.config.page_method_name}(num = nil)
28
+ num = num.respond_to?(:to_i) ? num.to_i : 1
16
29
  per_page = max_per_page && (default_per_page > max_per_page) ? max_per_page : default_per_page
17
- limit(per_page).offset(per_page * ((num = num.to_i - 1) < 0 ? 0 : num)).extending do
18
- include Kaminari::ActiveRecordRelationMethods
19
- include Kaminari::PageScopeMethods
20
- end
30
+ # spawn only once rather than calling limit, offset, and extending, each of which copies the Relation
31
+ all.spawn.limit!(per_page).offset!(per_page * ((num = num.to_i - 1) < 0 ? 0 : num)).extending!(Kaminari::ActiveRecordPageScope)
21
32
  end
22
33
  RUBY
23
34
  end
@@ -18,19 +18,24 @@ module Kaminari
18
18
  return @total_count if defined?(@total_count) && @total_count
19
19
 
20
20
  # There are some cases that total count can be deduced from loaded records
21
- if loaded?
21
+ # (except with per(0) or without a limit, where loaded records say nothing about the total count)
22
+ if loaded? && limit_value.to_i != 0
22
23
  # Total count has to be 0 if loaded records are 0
23
24
  return @total_count = 0 if (current_page == 1) && @records.empty?
24
25
  # Total count is calculable at the last page
25
- return @total_count = (current_page - 1) * limit_value + @records.length if @records.any? && (@records.length < limit_value)
26
+ return @total_count = offset_value + @records.length if @records.any? && (@records.length < limit_value)
26
27
  end
27
28
 
28
29
  # #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
29
30
  c = except(:offset, :limit, :order)
30
31
  # Remove includes only if they are irrelevant
31
- c = c.except(:includes) unless references_eager_loaded_tables?
32
+ c = c.except(:includes, :eager_load, :preload) unless references_eager_loaded_tables?
32
33
 
33
- c = c.limit(max_pages * limit_value) if max_pages && max_pages.respond_to?(:*)
34
+ # Count up to max_pages pages (not with per(0), where LIMIT 0 would make the total count 0, nor without a limit)
35
+ c = c.limit(max_pages * limit_value) if max_pages && max_pages.respond_to?(:*) && limit_value.to_i != 0
36
+
37
+ # Count the groups in the database instead of fetching a row per group
38
+ return @total_count = count_groups(c) if c.group_values.any? && !c.eager_loading?
34
39
 
35
40
  # .group returns an OrderedHash that responds to #count
36
41
  c = c.count(column_name)
@@ -50,6 +55,33 @@ module Kaminari
50
55
  def without_count
51
56
  extend ::Kaminari::PaginatableWithoutCount
52
57
  end
58
+
59
+ private
60
+
61
+ # Overrides PageScopeMethods#limit_and_offset not to copy the Relation twice via limit and offset
62
+ def limit_and_offset(new_limit, new_offset)
63
+ spawn.limit!(new_limit).offset!(new_offset)
64
+ end
65
+
66
+ # SELECT COUNT(*) FROM (SELECT 1 FROM ... GROUP BY ...) subquery_for_count
67
+ def count_groups(relation)
68
+ # Each group is one row unless DISTINCT collapses some of them
69
+ relation = relation.except(:distinct)
70
+ having = relation.respond_to?(:having_clause) ? !relation.having_clause.empty? : relation.having_values.any?
71
+ # The HAVING clause may refer to aliases in the custom SELECT clause. Otherwise, SELECT 1 is valid with any GROUP BY clause.
72
+ relation = relation.except(:select).select('1') unless having && relation.select_values.any?
73
+
74
+ sql = relation.to_sql
75
+ return 0 if sql.blank? # Relation#none on Active Record < 5
76
+
77
+ sql = "SELECT COUNT(*) FROM (#{sql}) subquery_for_count"
78
+ count = if klass.respond_to? :with_connection
79
+ klass.with_connection {|connection| connection.select_value sql, "#{klass.name} Count" }
80
+ else
81
+ klass.connection.select_value sql, "#{klass.name} Count"
82
+ end
83
+ count.to_i
84
+ end
53
85
  end
54
86
 
55
87
  # A module that makes AR::Relation paginatable without having to cast another SELECT COUNT query
@@ -59,15 +91,17 @@ module Kaminari
59
91
  refine ::ActiveRecord::Relation do
60
92
  private
61
93
 
62
- # Update multiple instance variables that holds `limit` to a given value
94
+ # Update multiple instance variables that hold `limit` to a given value
63
95
  def set_limit_value(new_limit)
64
96
  @values[:limit] = new_limit
65
97
 
66
98
  if @arel
67
- case @arel.limit
68
- when Integer
99
+ case @arel.limit.class.name
100
+ when 'Integer', 'Fixnum'
69
101
  @arel.limit = new_limit
70
- when Arel::Nodes::BindParam
102
+ when 'ActiveModel::Attribute::WithCastValue' # comparing by class name because ActiveModel::Attribute::WithCastValue is a private constant
103
+ @arel.limit = build_cast_value 'LIMIT', new_limit
104
+ when 'Arel::Nodes::BindParam'
71
105
  if @arel.limit.respond_to?(:value)
72
106
  @arel.limit = Arel::Nodes::BindParam.new(@arel.limit.value.with_cast_value(new_limit))
73
107
  end
@@ -76,13 +110,8 @@ module Kaminari
76
110
  end
77
111
  end
78
112
  end
79
- end
80
- end
81
- # NOTE: ending all modules and reopening again because using has to be called from the toplevel in Ruby 2.0
82
- using Kaminari::PaginatableWithoutCount::LimitValueSetter
113
+ using Kaminari::PaginatableWithoutCount::LimitValueSetter
83
114
 
84
- module Kaminari
85
- module PaginatableWithoutCount
86
115
  # Overwrite AR::Relation#load to actually load one more record to judge if the page has next page
87
116
  # then store the result in @_has_next ivar
88
117
  def load
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kaminari
4
4
  module Activerecord
5
- VERSION = '1.2.1'
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,108 +1,118 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kaminari-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - Akira Matsuda
8
- autorequire:
7
+ - Akira Matsuda
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-05-27 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: kaminari-core
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '='
18
- - !ruby/object:Gem::Version
19
- version: 1.2.1
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '='
25
- - !ruby/object:Gem::Version
26
- version: 1.2.1
27
- - !ruby/object:Gem::Dependency
28
- name: activerecord
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '1.12'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '1.12'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '10.0'
12
+ - !ruby/object:Gem::Dependency
13
+ name: kaminari-core
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ -
17
+ - "="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ -
25
+ - "="
26
+ - !ruby/object:Gem::Version
27
+ version: 1.3.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: activerecord
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ -
33
+ - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ -
41
+ - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ - !ruby/object:Gem::Dependency
45
+ name: bundler
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ -
49
+ - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "1.12"
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ -
57
+ - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "1.12"
60
+ - !ruby/object:Gem::Dependency
61
+ name: rake
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ -
65
+ - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "10.0"
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ -
73
+ - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "10.0"
69
76
  description: kaminari-activerecord lets your Active Record models be paginatable
70
77
  email:
71
- - ronnie@dio.jp
78
+ - ronnie@dio.jp
72
79
  executables: []
73
80
  extensions: []
74
81
  extra_rdoc_files: []
75
82
  files:
76
- - CHANGELOG.md
77
- - MIT-LICENSE
78
- - README.md
79
- - kaminari-activerecord.gemspec
80
- - lib/kaminari/activerecord.rb
81
- - lib/kaminari/activerecord/active_record_extension.rb
82
- - lib/kaminari/activerecord/active_record_model_extension.rb
83
- - lib/kaminari/activerecord/active_record_relation_methods.rb
84
- - lib/kaminari/activerecord/version.rb
85
- homepage: https://github.com/kaminari/kaminari
83
+ - CHANGELOG.md
84
+ - MIT-LICENSE
85
+ - README.md
86
+ - kaminari-activerecord.gemspec
87
+ - lib/kaminari/activerecord.rb
88
+ - lib/kaminari/activerecord/active_record_extension.rb
89
+ - lib/kaminari/activerecord/active_record_model_extension.rb
90
+ - lib/kaminari/activerecord/active_record_relation_methods.rb
91
+ - lib/kaminari/activerecord/version.rb
92
+ homepage: "https://github.com/kaminari/kaminari"
86
93
  licenses:
87
- - MIT
88
- metadata: {}
89
- post_install_message:
94
+ - MIT
95
+ metadata:
96
+ changelog_uri: "https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md"
97
+ source_code_uri: "https://github.com/kaminari/kaminari/tree/master/kaminari-activerecord"
98
+ rubygems_mfa_required: "true"
90
99
  rdoc_options: []
91
100
  require_paths:
92
- - lib
101
+ - lib
93
102
  required_ruby_version: !ruby/object:Gem::Requirement
94
103
  requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- version: 2.0.0
104
+ -
105
+ - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 2.0.0
98
108
  required_rubygems_version: !ruby/object:Gem::Requirement
99
109
  requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: '0'
110
+ -
111
+ - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: "0"
103
114
  requirements: []
104
- rubygems_version: 3.2.0.pre1
105
- signing_key:
115
+ rubygems_version: 4.1.0.beta2
106
116
  specification_version: 4
107
117
  summary: Kaminari Active Record adapter
108
118
  test_files: []