Ransack: Ransack throws an error when doing a query that joins twice to the same table.

Created on 2 Dec 2020  路  3Comments  路  Source: activerecord-hackery/ransack

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  gem 'rails', '6.0.3.4'
  gem 'pg'
  gem 'pry'
  gem 'ransack', '2.4.0', require: false
end

require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'ransack'

ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: 'ransack_test')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :arms, force: true do |t|
    t.string :name
    t.integer :amount_of_finger
  end

  create_table :robots, force: true do |t|
    t.string :name
    t.references :left_arm, index: true, foreign_key: { to_table: :arms }
    t.references :right_arm, index: true, foreign_key: { to_table: :arms }
  end
end

class Robot < ActiveRecord::Base
  belongs_to :right_arm, dependent: :destroy, class_name: 'Arm'
  belongs_to :left_arm, dependent: :destroy, class_name: 'Arm'
end

class Arm < ActiveRecord::Base
  has_one :robot
end

class RansackFindsTheObject < ActiveSupport::TestCase
  def setup
    @left_arm = Arm.create!(name: 'left', amount_of_finger: 6)
    @right_arm = Arm.create!(name: 'right', amount_of_finger: 3)
    @robot = Robot.create!(name: 'Wall-e', left_arm: @left_arm, right_arm: @right_arm)
    @q = {'right_arm_name_eq' => 'right', 'left_arm_name_eq' => 'left'}
  end


  def test_ransack_filtering_works
    assert_includes Robot.ransack(@q).result, @robot
  end
end

This proves the error with Rails version 6.0.3 and Ransack version 2.4.0
This throws an error:

Error:
RansackFindsTheObject#test_ransack_filtering_works:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "left_arms_robots"
LINE 1: ..."right_arm_id" WHERE ("arms"."name" = 'right' AND "left_arms...

It was also evaluated for an older version of rails (5.2.4) with Ransack version 2.4.0
And this works:

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  gem 'rails', '5.2.4'
  gem 'pg'
  gem 'pry'
  gem 'ransack', '2.4.0', require: false
end

require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'ransack'

ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: 'ransack_test')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :arms, force: true do |t|
    t.string :name
    t.integer :amount_of_finger
  end

  create_table :robots, force: true do |t|
    t.string :name
    t.references :left_arm, index: true, foreign_key: { to_table: :arms }
    t.references :right_arm, index: true, foreign_key: { to_table: :arms }
  end
end

class Robot < ActiveRecord::Base
  belongs_to :right_arm, dependent: :destroy, class_name: 'Arm'
  belongs_to :left_arm, dependent: :destroy, class_name: 'Arm'
end

class Arm < ActiveRecord::Base
  has_one :robot
end

class RansackFindsTheObject < ActiveSupport::TestCase
  def setup
    @left_arm = Arm.create!(name: 'left', amount_of_finger: 6)
    @right_arm = Arm.create!(name: 'right', amount_of_finger: 3)
    @robot = Robot.create!(name: 'Wall-e', left_arm: @left_arm, right_arm: @right_arm)
    @q = {'right_arm_name_eq' => 'right', 'left_arm_name_eq' => 'left'}
  end


  def test_ransack_filtering_works
    assert_includes Robot.ransack(@q).result, @robot
  end
end

Also works for rails 6.1.0.rc2 with Ransack 2.4.0

But for Rails version 6.0.3 and Ransack version 2.3.2 It continues failing

This is related to issue #1151 and #1144

Most helpful comment

According to git bisect, this issue has been addressed at Rails 6-0-stable branch via https://github.com/rails/rails/commit/f9ba52477ca288e7effa5f6794ae3df3f4e982bc .

If Rails 6.0.4 is released this fix should be included.

All 3 comments

I have faced the same issue with Rails 6.0.2 and Ransack 2.4.0

After upgrading Rails version to 6.1.0 it all works well!

According to git bisect, this issue has been addressed at Rails 6-0-stable branch via https://github.com/rails/rails/commit/f9ba52477ca288e7effa5f6794ae3df3f4e982bc .

If Rails 6.0.4 is released this fix should be included.

An updated test works for me with Postgres:

unless File.exist?('Gemfile')
  File.write('Gemfile', <<-GEMFILE)
    source 'https://rubygems.org'
    # Rails master
    gem 'rails', github: 'rails/rails', branch: '6-1-stable'
    # Rails last release
    # gem 'rails'
    gem 'sqlite3'
    gem 'ransack', github: 'activerecord-hackery/ransack'
  GEMFILE

  system 'bundle install'
end

require 'bundler'
Bundler.setup(:default)

require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'ransack'

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(
  adapter: 'postgresql',
  database: 'ransack_test',
  host: 'postgres',
  user: 'username',
  password: 'password'
)
ActiveRecord::Base.logger = Logger.new(STDOUT)

# Display versions.
message = "Running test case with Ruby #{RUBY_VERSION}, Active Record #{
  ::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION} and #{
  ::ActiveRecord::Base.connection.adapter_name}"
line = '=' * message.length
puts line, message, line

ActiveRecord::Schema.define do
  create_table :arms, force: true do |t|
    t.string :name
    t.integer :amount_of_finger
  end

  create_table :robots, force: true do |t|
    t.string :name
    t.references :left_arm, index: true #, foreign_key: { to_table: :arms }
    t.references :right_arm, index: true #, foreign_key: { to_table: :arms }
  end
end

class Robot < ActiveRecord::Base
  belongs_to :right_arm, dependent: :destroy, class_name: 'Arm'
  belongs_to :left_arm, dependent: :destroy, class_name: 'Arm'
end

class Arm < ActiveRecord::Base
  has_one :robot
end

class RansackFindsTheObject < ActiveSupport::TestCase
  def setup
    @left_arm = Arm.create!(name: 'left', amount_of_finger: 6)
    @right_arm = Arm.create!(name: 'right', amount_of_finger: 3)
    @robot = Robot.create!(name: 'Wall-e', left_arm: @left_arm, right_arm: @right_arm)
    @q = {'right_arm_name_eq' => 'right', 'left_arm_name_eq' => 'left'}
  end

  def test_ransack_filtering_works
    assert_includes Robot.ransack(@q).result, @robot
  end
end
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ivanovaleksey picture ivanovaleksey  路  3Comments

seanfcarroll picture seanfcarroll  路  4Comments

tagrudev picture tagrudev  路  3Comments

MatsumotoHiroko picture MatsumotoHiroko  路  4Comments

seanfcarroll picture seanfcarroll  路  3Comments