Skip to content

Instantly share code, notes, and snippets.

@rzane

rzane/README.md

Last active Jul 18, 2020
Embed
What would you like to do?
QueryExtensions

QueryExtensions

First, you'll need to incorporate the extension:

class ApplicationRecord < ActiveRecord::Base
  extend QueryExtensions
end

Now, you can use it like this:

class Author < ApplicationRecord
end

Author.where_has { age.eq(29).or(age.gt(40)) }
# SELECT "authors".* FROM "authors" WHERE ("authors"."age" = 29 OR "authors"."age" > 40)

Author.joins(:posts).where_has { Post[:title].matches("Breaking News:%") }
# SELECT "authors".* FROM "authors" INNER JOIN "posts" ON "posts"."author_id" = "authors"."id" WHERE "posts"."title" LIKE 'Breaking News:%'

In the example above, age and Post[:title] are instances of Arel::Attributes::Attribute.

module QueryExtensions
def [](name)
arel_table[name]
end
def where_has(&block)
where DSL.new(self).evaluate(&block)
end
def selecting(&block)
select DSL.new(self).evaluate(&block)
end
def ordering(&block)
order DSL.new(self).evaluate(&block)
end
class DSL
def initialize(model)
@model = model
end
def evaluate(&block)
if block.arity.zero?
instance_eval(&block)
else
instance_exec(self, &block)
end
end
private
def respond_to_missing?(name, *)
@model.column_names.include?(name.to_s) || super
end
def method_missing(name, *args, &block)
if @model.column_names.include?(name.to_s)
@model.arel_table[name]
else
super
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment