Skip to content

Instantly share code, notes, and snippets.

@firien
Last active August 29, 2015 14:17
Show Gist options
  • Save firien/1ba3973b190fae41aa64 to your computer and use it in GitHub Desktop.
Save firien/1ba3973b190fae41aa64 to your computer and use it in GitHub Desktop.
missing binds
gem 'activerecord', '4.1.10'#uncomment to load latest AR gem
require 'active_record'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: ':memory:'
)
puts "-- arel #{Arel::VERSION}"
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :tasks do |t|
t.integer :assigned_id
t.string :assigned_type
end
create_table :people do |t|
t.string :name
end
create_table :roles do |t|
t.integer :person_id
end
end
Task = Class.new ActiveRecord::Base
Role = Class.new ActiveRecord::Base
class Person < ActiveRecord::Base
def tasks
str = Arel::VERSION.to_i == 5 ? 'Role' : Arel::Nodes::Quoted.new('Role')
person_arel = Task.where(assigned_id: self.id, assigned_type: 'Person')
_roles = Role.where(person_id: self.id).select(:id).as('_roles')
roles_arel = Task.joins(Arel::Nodes::InnerJoin.new(_roles, Arel::Nodes::On.new(
Arel::Nodes::Equality.new(_roles[:id], Task.arel_table[:assigned_id]).and(
Arel::Nodes::Equality.new(Task.arel_table[:assigned_type], str))
)))
union = person_arel.union roles_arel
tasks = Arel::Nodes::TableAlias.new(union, :tasks)
Task.from(tasks)
end
end
me = Person.create(name: 'me')
puts me.tasks.to_sql
__END__
produces
-- arel 5.0.1
SELECT "tasks".* FROM (
SELECT "tasks".* FROM "tasks" WHERE "tasks"."assigned_id" = 1 AND "tasks"."assigned_type" = 'Person'
UNION
SELECT "tasks".* FROM "tasks" INNER JOIN (
SELECT "roles"."id" FROM "roles" WHERE "roles"."person_id" = 1
) _roles ON _roles."id" = "tasks"."assigned_id" AND "tasks"."assigned_type" = 'Role'
) "df"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment