Skip to content

Instantly share code, notes, and snippets.

@shekibobo
Created April 10, 2014 20:16
Show Gist options
  • Save shekibobo/10418963 to your computer and use it in GitHub Desktop.
Save shekibobo/10418963 to your computer and use it in GitHub Desktop.
Testing failures of arel related to `eager_load` queries not generating correct `to_sql`.
unless File.exists?('Gemfile')
File.write('Gemfile', <<-GEMFILE)
source 'https://rubygems.org'
gem 'rails', github: 'rails/rails'
gem 'sqlite3'
gem 'pry'
gem 'pg'
GEMFILE
system 'bundle'
end
PG_SPEC = {
:adapter => 'postgresql',
:host => 'localhost',
:database => 'test_active_record_eager_load_sql',
:username => 'joshuakovach',
:encoding => 'utf8'
}
require 'bundler'
Bundler.setup(:default)
require 'rails'
require 'pg'
require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'pry'
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(PG_SPEC.merge('database' => 'postgres', 'schema_search_path' => 'public'))
ActiveRecord::Base.connection.drop_database PG_SPEC[:database] rescue nil
# create new
ActiveRecord::Base.connection.create_database(PG_SPEC[:database])
ActiveRecord::Base.establish_connection(PG_SPEC)
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :divisions do |t|
end
create_table :users do |t|
t.references :division, index: true
end
create_table :admins do |t|
t.references :division, index: true
end
end
class User < ActiveRecord::Base
belongs_to :division
end
class Admin < ActiveRecord::Base
belongs_to :division
end
class Division < ActiveRecord::Base
has_many :users
has_many :admins
scope :without_users, -> { eager_load(:users).merge(User.where(id: nil)) }
scope :without_admins, -> { eager_load(:admins).merge(Admin.where(id: nil)) }
def self.without_users_or_without_admins
union = without_users.union(without_admins)
from(arel_table.create_table_alias(union, :divisions))
end
end
class BugTest < Minitest::Test
def test_active_record_eager_load_sql
division_without_admins = Division.create!
division_without_users = Division.create!
division_without_users.admins << Admin.create!
division_without_admins.users << User.create!
binding.pry
assert_includes [division_without_admins, division_without_users], Division.without_users_or_without_admins
end
end
@shekibobo
Copy link
Author

D, [2014-04-10T16:17:51.369954 #66563] DEBUG -- :   Division Load (0.8ms)  SELECT "divisions".* FROM ( SELECT "divisions".* FROM "divisions"  WHERE "users"."id" IS NULL UNION SELECT "divisions".* FROM "divisions"  WHERE "admins"."id" IS NULL ) "divisions"
E, [2014-04-10T16:17:51.370085 #66563] ERROR -- : PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "users"
LINE 1: ...OM ( SELECT "divisions".* FROM "divisions"  WHERE "users"."i...
                                                             ^
: SELECT "divisions".* FROM ( SELECT "divisions".* FROM "divisions"  WHERE "users"."id" IS NULL UNION SELECT "divisions".* FROM "divisions"  WHERE "admins"."id" IS NULL ) "divisions"

This appears to be using eager_load premature and incorrect to_sql string to union these two together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment