Skip to content

Ransack generates redundant left join statements #1433

@itsalongstory

Description

@itsalongstory

test_ransack.rb

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'
  gem 'activerecord', '~> 8.1', '>= 8.1.1', require: "active_record"
  gem 'sqlite3', '~> 2.9'
  gem 'ransack', '~> 4.4', '>= 4.4.1'
  gem 'minitest', '~> 6.0', '>= 6.0.1', require: "minitest/autorun"
end

ActiveRecord::Base.establish_connection(
  adapter:  "sqlite3",
  database: "./test_ransack_search"
)

ActiveRecord::Schema.define do
  drop_table(:authors, if_exists: true)
  drop_table(:articles, if_exists: true)
  drop_table(:comments, if_exists: true)

  create_table :authors do |t|
    t.string :name
  end

  create_table :articles do |t|
    t.belongs_to :author
    t.string :title
  end

  create_table :comments do |t|
    t.belongs_to :article
    t.string :content
  end
end

class ApplicationRecord < ActiveRecord::Base
  primary_abstract_class

  def self.ransackable_attributes(auth_object = nil)
    authorizable_ransackable_attributes
  end

  def self.ransackable_associations(auth_object = nil)
    authorizable_ransackable_associations
  end
end

class Author < ApplicationRecord
  has_many :articles
end

class Article < ApplicationRecord
  has_many :comments
  belongs_to :author
end

class Comment < ApplicationRecord
  belongs_to :article
end

class MyTest < Minitest::Test
  # success
  def test_1
    query_params = { article_title_eq: 'abc' }
    assert_equal "SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" WHERE \"articles\".\"title\" = 'abc'", Comment.joins(:article).ransack(query_params).result.to_sql
  end

  # failure
  def test_2
    query_params = { article_author_name_eq: 'abc' }
    assert_equal "SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'", Comment.joins(article: :author).ransack(query_params).result.to_sql
  end
end
deploy@fms-test:~$ ruby test_ransack.rb 
Fetching gem metadata from https://rubygems.org/........
Resolving dependencies...
Fetching base64 0.3.0
Fetching bigdecimal 4.0.1
Fetching json 2.18.0
Fetching connection_pool 3.0.2
Fetching drb 2.2.3
Fetching logger 1.7.0
Fetching prism 1.7.0
Fetching concurrent-ruby 1.3.6
Installing base64 0.3.0
Fetching securerandom 0.4.1
Installing bigdecimal 4.0.1 with native extensions
Installing json 2.18.0 with native extensions
Installing connection_pool 3.0.2
Fetching uri 1.1.1
Installing drb 2.2.3
Fetching timeout 0.6.0
Installing logger 1.7.0
Fetching sqlite3 2.9.0 (x86_64-linux-gnu)
Installing prism 1.7.0 with native extensions
Installing concurrent-ruby 1.3.6
Installing securerandom 0.4.1
Installing uri 1.1.1
Installing timeout 0.6.0
Fetching i18n 1.14.8
Installing i18n 1.14.8
Installing sqlite3 2.9.0 (x86_64-linux-gnu)
Fetching minitest 6.0.1
Installing minitest 6.0.1
Fetching activesupport 8.1.1
Installing activesupport 8.1.1
Fetching activemodel 8.1.1
Installing activemodel 8.1.1
Fetching activerecord 8.1.1
Installing activerecord 8.1.1
Fetching ransack 4.4.1
Installing ransack 4.4.1
-- drop_table(:authors, {if_exists: true})
   -> 0.0830s
-- drop_table(:articles, {if_exists: true})
   -> 0.0002s
-- drop_table(:comments, {if_exists: true})
   -> 0.0001s
-- create_table(:authors)
   -> 0.0168s
-- create_table(:articles)
   -> 0.0008s
-- create_table(:comments)
   -> 0.0007s
Run options: --seed 26369

# Running:

.F

Finished in 0.037279s, 53.6496 runs/s, 53.6496 assertions/s.

  1) Failure:
MyTest#test_2 [r1433.rb:71]:
--- expected
+++ actual
@@ -1 +1 @@
-"SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'"
+"SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" LEFT OUTER JOIN \"authors\" AS \"authors_articles\" ON \"authors_articles\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'"


2 runs, 2 assertions, 1 failures, 0 errors, 0 skips

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions