class Analytics::TopAuthors
def initialize(since: 30.days.ago)
@since = since
end
def call(limit: 20)
sql = <<~SQL
SELECT author_id, COUNT(*) AS snips_count
FROM snips
WHERE created_at >= $1
GROUP BY author_id
ORDER BY snips_count DESC
LIMIT $2
SQL
binds = [
ActiveRecord::Relation::QueryAttribute.new('since', @since, ActiveRecord::Type::DateTime.new),
ActiveRecord::Relation::QueryAttribute.new('limit', limit, ActiveRecord::Type::Integer.new)
]
ApplicationRecord.connection.exec_query(sql, 'TopAuthors', binds).to_a
end
end
Sometimes raw SQL is the cleanest approach—just keep it safe. Use exec_query with bind params instead of interpolating values. You get both safety and correctness with types.