Skip to content

Commit

Permalink
Fix: total_count with GROUPED STI relation
Browse files Browse the repository at this point in the history
When querying a subtype on a STI table, a 'hard scope' is applied that
is incompatible with the use of `model.from(subquery)`

This fix removes any type restriction from the _outer_ query (because
the subquery already has the restriction).

Introduced by kaminari#979
  • Loading branch information
bendilley committed Feb 20, 2020
1 parent 7347292 commit 2c3a957
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
Expand Up @@ -34,7 +34,8 @@ def total_count(column_name = :all, _options = nil) #:nodoc:

# Handle grouping with a subquery
@total_count = if c.group_values.any?
c.model.from(c.except(:select).select("1")).count
# STI can place a 'hard scope' on the model which doesn't work on the outer query here
c.model.unscope(where: :type).from(c.except(:select).select("1")).count
else
c.count(column_name)
end
Expand Down
15 changes: 15 additions & 0 deletions kaminari-core/test/fake_app/active_record/models.rb
Expand Up @@ -51,6 +51,20 @@ class Product < ActiveRecord::Base
class Device < Product
end

# STI table: animals
class Animal < ActiveRecord::Base
end
class Mammal < Animal
end
class Dog < Mammal
end
class Cat < Mammal
end
class Insect < Animal
end
class Grasshopper < Insect
end

# migrations
ActiveRecord::Migration.verbose = false
ActiveRecord::Tasks::DatabaseTasks.root = Dir.pwd
Expand All @@ -66,6 +80,7 @@ def self.up
create_table(:authorships) {|t| t.integer :user_id; t.integer :book_id }
create_table(:user_addresses) {|t| t.string :street; t.integer :user_id }
create_table(:devices) {|t| t.string :name; t.integer :age}
create_table(:animals) {|t| t.string :type; t.string :name}
end
end
CreateAllTables.up
Expand Up @@ -14,6 +14,11 @@ class ActiveRecordRelationMethodsTest < ActiveSupport::TestCase
@books3 = 4.times.map {|i| @author3.books_authored.create!(title: "subject%03d" % i) }
@readers = 4.times.map { User.create! name: 'reader' }
@books.each {|book| book.readers << @readers }
[
['Fenton', Dog], ['Bob', Dog],
['Garfield', Cat], ['Bob', Cat],
['Caine', Grasshopper]
].each { |name, type| type.create! name: name }
end
teardown do
Book.delete_all
Expand Down Expand Up @@ -100,6 +105,11 @@ class ActiveRecordRelationMethodsTest < ActiveSupport::TestCase
assert_equal 2, Authorship.group(:user_id).having("COUNT(book_id) >= 3").page(1).total_count
end

test 'calculating STI total_count with GROUP BY clause' do
# A type-based restriction places a scope on the model
assert_equal 3, Mammal.group(:name).page(1).total_count
end

test 'total_count with max_pages does not add LIMIT' do
begin
subscriber = ActiveSupport::Notifications.subscribe 'sql.active_record' do |_, __, ___, ____, payload|
Expand Down

0 comments on commit 2c3a957

Please sign in to comment.