Last active
August 29, 2015 13:55
-
-
Save joekhoobyar/8699750 to your computer and use it in GitHub Desktop.
ActiveRecord query extension: where_exists(related,*where_params)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveRecord | |
module FinderMethods | |
# This simple class acts as a "stand-in" for your association, enabling us to reuse logic | |
# in ::ActiveRecord::Associations::AssociationScope. | |
class ExistingAssociation < Struct.new(:klass, :owner, :reflection) | |
delegate :interpolate, to: :klass | |
def initialize klass, related | |
raise ArgumentError if Hash===related && related.length > 1 | |
related, subjoins = Array(related).flatten | |
reflection = klass.reflect_on_association(related) | |
super reflection.klass, klass.arel_table, reflection | |
end | |
def scope | |
::ActiveRecord::Associations::AssociationScope.new(self).scope | |
end | |
end | |
# Build a WHERE clause that checks the existance of a related association or relation. | |
# Any (optional) following arguments will be treated as separate invocations of where(*arg), | |
# with the additional convenience that a Symbol on the right-hand side will be treated as column | |
# from this model's table. | |
def where_exists(related, *where_params) | |
relation = | |
case related | |
when ActiveRecord::Relation then related | |
else ExistingAssociation.new(@klass, related).scope | |
end | |
relation = relation.send(:construct_relation_for_association_find, | |
relation.send(:construct_join_dependency_for_association_find)). | |
except(:select, :order). | |
select("1 AS one") | |
where("EXISTS (#{where_params.inject relation do |subq,where_param| | |
if not Hash===where_param then subq.where(where_param) else | |
subq.where(Hash[ where_param.map do |k,v| | |
[k, Symbol===v ? @klass.arel_table[v] : v] | |
end ]) | |
end | |
end.to_sql})") | |
end | |
end | |
module Querying | |
delegate :where_exists, to: :scoped | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment