Quo: Query Objects for ActiveRecord & Collections

Composable, testable, and reusable query objects for Ruby on Rails

What is Quo?

quo is a Ruby gem that helps you organize database and collection queries into reusable, composable, and testable objects with a clean, fluent API.

Why use Quo?

  • Organize complex queries: Encapsulate query logic in dedicated, testable classes
  • Composable: Combine multiple query objects using the + operator
  • Type-safe: Built on the Literal gem for typed properties with validation
  • Pagination built-in: Automatic pagination for both database and collection queries
  • Flexible: Works with ActiveRecord relations and plain Ruby collections
  • Fluent API: Chain methods just like ActiveRecord

Quick Example

# Define query objects to encapsulate query logic
class RecentPostsQuery < Quo::RelationBackedQuery
  # Type-safe properties with defaults
  prop :days_ago, Integer, default: -> { 7 }

  def query
    Post.where(Post.arel_table[:created_at].gt(days_ago.days.ago))
      .order(created_at: :desc)
  end
end

# Use queries with pagination
posts_query = RecentPostsQuery.new(days_ago: 30, page: 1, page_size: 10)
page1 = posts_query.results
# => Returns first 10 posts from the last 30 days

# Navigate between pages
page2_query = posts_query.next_page_query
page2 = page2_query.results
# => Returns next 10 posts

# Compose queries
class CommentNotSpamQuery < Quo::RelationBackedQuery
  prop :spam_score_threshold, _Float(0..1.0)

  def query
    comments = Comment.arel_table
    Comment.where(
      comments[:spam_score].eq(nil).or(comments[:spam_score].lt(spam_score_threshold))
    )
  end
end

# Get recent posts (last 10 days) which have comments that are not spam
posts_last_10_days = RecentPostsQuery.new(days_ago: 10).joins(:comments)
query = posts_last_10_days + CommentNotSpamQuery.new(spam_score_threshold: 0.5)

# Transform results
transformed_query = query.transform { |post| PostPresenter.new(post) }

# Work with result sets
transformed_query.results.each do |presenter|
  puts presenter.formatted_title
end

Getting Started

Explore the documentation to learn more:

Installation

Add to your Gemfile:

gem "quo"

Then execute:

$ bundle install

Requirements

  • Ruby 3.2+
  • Rails 7.2+

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/quo.

License

The gem is available as open source under the terms of the MIT License.

Inspiration

This implementation is inspired by the Rectify gem by Andy Pike. Thanks for the inspiration!

Key differences to Quo:

  • Much broader scope—bundles forms, presenters, commands, AND queries where Quo focuses only on queries
  • No longer actively maintained
  • Uses Wisper pub/sub pattern for commands; Quo has simpler return values
  • Lacks the type-safety emphasis that Quo provides
  • Query composition with | operator directly inspired Quo’s composable design

Quo as an alternative?

Quo can be seen as a successor to Rectify’s query object concepts.


Quo | Copyright © 2025. Licensed under the MIT License.