Skip to content

Instantly share code, notes, and snippets.

@Agowan
Last active August 29, 2015 13:56
Show Gist options
  • Save Agowan/8930922 to your computer and use it in GitHub Desktop.
Save Agowan/8930922 to your computer and use it in GitHub Desktop.
A way of encapsulate custom sql within objects and of course it's possible to make really clean with more inheritance.
# encoding: utf-8
class Context
def sanitize_sql(array)
self.class.sanitize_sql(array)
end
def select_all(sql)
self.class.select_all(sql)
end
def execute(sql)
self.class.execute(sql)
end
def self.sanitize_sql(array)
compress ActiveRecord::Base.send(:sanitize_sql_array, array)
end
def compress(sql)
sql.gsub(/\n/,"").squeeze(' ').strip
end
def self.select_all(sql)
ActiveRecord::Base.connection.select_all(sql)
end
def self.execute(sql)
ActiveRecord::Base.connection.execute(sql)
end
end
# encoding utf-8
class Statistics::Orders < Context
class Result
include Virtus
attribute :total, Integer
attribute :delivered, Integer
attribute :year, Integer
attribute :month, Integer
def month_name
date.strftime("%B")
end
def date
@date ||= Date.new(year, month, 1)
end
end
def initialize(from = Date.today.beginning_of_month, to = Date.today.end_of_month)
from.is_a?(Date) or raise "from is a #{from.class} expected Date"
to.is_a?(Date) or raise "to is a #{to.class} expected Date"
@from = from
@to = to
end
def each &block
orders.each &block
end
def sum
@sum ||= Statistics::Result.new.tap do |r|
r.total = orders.sum(&:total)
r.delivered = orders.sum(&:delivered)
end
end
protected
def orders
@orders ||= select_all(sql).map { |h| Result.new h }
end
def sql
sanitize_sql([raw_sql, @from, @to])
end
def raw_sql
compress <<-SQL
SELECT COUNT(*) "total",
SUM(CASE WHEN "delivered_at" IS NOT NULL THEN 1 ELSE 0 END) AS "delivered",
EXTRACT(year from created_at) AS "year",
EXTRACT(month from created_at) AS "month"
FROM "orders"
INNER JOIN "users" ON "orders"."user_id" = "users"."id"
WHERE "users"."active" = 1
AND "created_at" >= ?
AND "created_at" <= ?
GROUP BY EXTRACT(year from created_at)
EXTRACT(month from created_at)
SQL
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment