Skip to content

Instantly share code, notes, and snippets.

@inopinatus
Last active July 13, 2019 06:33
Show Gist options
  • Save inopinatus/43d6b7af67b592faf116dc3050f66434 to your computer and use it in GitHub Desktop.
Save inopinatus/43d6b7af67b592faf116dc3050f66434 to your computer and use it in GitHub Desktop.
Delegated relational composition for OR'ing polymorphic ActiveRecord associations
module Taskable
extend ActiveSupport::Concern
included do
has_many :tasks, as: :taskable
end
def tasks
task_relations.inject(super) do |this, rel|
this.or(rel.extending(AllTasks).all_tasks)
end
end
def task_relations
[]
end
module AllTasks
def all_tasks
Task.where(taskable: self)
end
end
end
class Task < ApplicationRecord
belongs_to :taskable, polymorphic: true
end
class Team < ApplicationRecord
include Taskable
has_many :accounts
has_many :businesses
def task_relations
super | [accounts, businesses]
end
end
class Account < ApplicationRecord
include Taskable
belongs_to :team
end
class Business < ApplicationRecord
include Taskable
belongs_to :team
end
@inopinatus
Copy link
Author

inopinatus commented Jul 13, 2019

Originally written in response to https://www.reddit.com/r/rails/comments/cchp51/is_this_sql_worth_writing_in_arel_ar_etc/. This was a fun little exercise and ultimately redundant because I then realised it is equivalent to writing

class Team < ApplicationRecord
  def all_tasks
    Task.where(taskable: [self, accounts, businesses])
  end

because Rails does the right thing with expanding the polymorphic subqueries. However, it does illustrate of couple of nice techniques, should you need them.

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