Skip to content

Instantly share code, notes, and snippets.

@gylaz
Last active January 2, 2016 17:49
Show Gist options
  • Save gylaz/8339463 to your computer and use it in GitHub Desktop.
Save gylaz/8339463 to your computer and use it in GitHub Desktop.
Polymorphic conditions
class Tag < ActiveRecord::Base
validates :name, presence: true, uniqueness: true
has_many :taggings
has_many :case_studies, through: :taggings, source: :taggable, source_type: 'CaseStudy'
has_many :posts, through: :taggings, source: :taggable, source_type: 'Post'
has_many :events, through: :taggings, source: :taggable, source_type: 'Event'
end
class Tagging < ActiveRecord::Base
validates :tag, presence: true
validates :taggable_id, presence: true
validates :taggable_type, presence: true
belongs_to :tag
belongs_to :taggable, polymorphic: true
def self.published
joins_posts.joins_events.joins_case_studies.
where(
'posts.published = ? OR events.id IS NOT NULL OR case_studies.id IS NOT NULL',
true
)
end
def self.chronological
order('coalesce(posts.published_at, events.start_date, case_studies.created_at) DESC')
end
def self.joins_posts
joins <<-SQL
LEFT JOIN posts
ON posts.id = taggings.taggable_id
AND taggings.taggable_type = 'Post'
SQL
end
def self.joins_events
joins <<-SQL
LEFT JOIN events
ON events.id = taggings.taggable_id
AND taggings.taggable_type = 'Event'
SQL
end
def self.joins_case_studies
joins <<-SQL
LEFT JOIN case_studies
ON case_studies.id = taggings.taggable_id
AND taggings.taggable_type = 'CaseStudy'
SQL
end
end
class TagsController < ApplicationController
def show
@tag = Tag.find(params[:id])
@taggings = @tag.taggings.published.chronological.page(params[:page])
end
end
@brittballard
Copy link

This is a genius solution. You are an amazing SQL engineer. I love you.

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