-
-
Notifications
You must be signed in to change notification settings - Fork 827
Description
I've gotta start this with thanks so much for Ransack, really the only time it ever gets in the way are during Rails upgrades 😄
I've seen other issues like the one I'm reporting (#1182, #1153, #1144) but they're on Rails 6.0 or have been fixed in the Rails 6.0 stable branch that will probably be released as Rails 6.0.4. We are upgrading to Rails 6.1 and am hitting table alias issues as part of that.
- If I use
gem 'rails', github: 'rails/rails', branch: '6-0-stable'then the below example will work. - If I use Rails 6.0.3.x then the first 2 assertions work and the last 2 generate a where clause using a table alias that does not exist.
- If I use Rails 6.1.x then the first 2 assertions work and the last 2 generate a where clause using a table alias that does not exist.
- If I use
gem 'rails', github: 'rails/rails', branch: '6-1-stable'then the first 2 assertions work and the last 2 generate a where clause using a table alias that does not exist.
In general the error raised is
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: user_applications_activities.name
As the table user_applications_activities does not exist in the gathering part of the query.
The only difference between the first 3 assertions and the last 3 are the ordering of the search models & attributes (user_name_or_user_application_name vs user_application_name_or_user_name).
I added another has relationship (to somethings) and started to query on that and it appears that it doesn't break the SQL as badly if that information helps debugging 🤷
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
# Issue DOES occur with Rails 6.1.x, 6-1-stable & 6.0.3
gem "activerecord", "~> 6.1.0", require: "active_record"
# gem "activerecord", github: "rails/rails", branch: "6-1-stable", require: "active_record"
# gem "activerecord", "~> 6.0.0", require: "active_record"
# Issue does NOT occur with Rails 6.0-stable (future 6.0.4)
# gem "activerecord", github: "rails/rails", branch: "6-0-stable", require: "active_record"
gem "ransack", github: "activerecord-hackery/ransack"
gem "niceql" # Just makes it nicer to see the SQL
gem "sqlite3"
gem "pry"
gem "byebug"
end
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table "activities", force: :cascade do |t|
t.integer "user_application_id"
t.string "content"
end
create_table "user_applications", force: :cascade do |t|
t.integer "user_id"
t.integer "something_id"
t.string "name"
end
create_table "users", force: :cascade do |t|
t.string "name"
end
create_table "somethings", force: :cascade do |t|
t.string "name"
end
end
class UserApplication < ActiveRecord::Base
belongs_to :user
belongs_to :something
end
class Something < ActiveRecord::Base
end
class Activity < ActiveRecord::Base
belongs_to :user_application
has_one :user, through: :user_application
has_one :something, through: :user_application
end
class User < ActiveRecord::Base
has_many :activities, through: :user_applications
has_many :user_applications
end
class BugTest < Minitest::Test
def setup
user1 = User.create!(name: "First User")
user2 = User.create!(name: "Last User")
first_something = Something.create!(name: "First Something")
user_1_application = UserApplication.create!(name: "First User Application", user: user1, something: first_something)
user_2_application = UserApplication.create!(name: "Last User Application", user: user2)
user_1_activity = Activity.create!(user_application: user_1_application, content: "First User Activity")
user_2_activity = Activity.create!(user_application: user_2_application, content: "Last User Activity")
end
def teardown
User.destroy_all
UserApplication.destroy_all
Activity.destroy_all
end
def test_join
# Tests swapping order of the search e.g. user_name_or_user_application_name vs user_application_name_or_user_name
#
# If user_application_name is first it works with Rails 6.0.3, 6.0.4 and 6.1
# If user_name is first it works with Rails 6.0.4 but breaks on Rails 6.0.3 and 6.1
#
# I included another has_* relationship to somethings as this seems to generate better SQL
# and not use an non-existant table alias.
#
# e.g. the SQL generated under Rails 6.1 for
#
# Activity.ransack(user_name_or_user_application_name_or_something_name_cont: "First").result.niceql
#
# SELECT "activities".*
# FROM "activities"
# LEFT OUTER JOIN "user_applications" ON "user_applications"."id" = "activities"."user_application_id"
# LEFT OUTER JOIN "users" ON "users"."id" = "user_applications"."user_id"
# LEFT OUTER JOIN "somethings" ON "somethings"."id" = "user_applications"."something_id"
# WHERE (("users"."name" LIKE '%First%' OR "user_applications_activities"."name" LIKE '%First%') OR "somethings"."name" LIKE '%First%')
#
results = Activity.ransack(user_application_name_or_user_name_cont: "something").result
assert_equal [], results.map(&:content)
results = Activity.ransack(user_application_name_or_user_name_cont: "First").result
assert_equal ["First User Activity"], results.map(&:content)
results = Activity.ransack(user_application_name_or_something_name_cont: "First").result
assert_equal ["First User Activity"], results.map(&:content)
results = Activity.ransack(user_name_or_user_application_name_cont: "something").result
assert_equal [], results.map(&:content)
results = Activity.ransack(user_name_or_user_application_name_cont: "First").result
assert_equal ["First User Activity"], results.map(&:content)
results = Activity.ransack(user_name_or_user_application_name_or_something_name_cont: "First").result
assert_equal ["First User Activity"], results.map(&:content)
end
end