Skip to content


Repository files navigation


Gem Version Build Status

Wharel helps you write concise Arel queries with ActiveRecord using Virtual Rows inspired by Sequel.

Although similar in spirit to gems like Squeel and BabySqueel, which provide sophisticated block-based interfaces for querying with Arel, Wharel is much much smaller. In fact, the core of the gem is only 30 lines long! It uses a single BasicObject as a clean room to evaluate the query block. That's really all there is to it.

For a more detailed explanation of the implementation, see this blog post.


Add this line to your application's Gemfile:

gem 'wharel', '~> 1.0.0'

And then execute:

$ bundle

Or install it yourself as:

$ gem install wharel


Suppose we have a model Post:

class Post < ApplicationRecord
  has_many :comments

And let's assume our Post has columns title and content.

Now, if we wanted to find all the posts with a title which matched the string "foo" and content which matched the string "bar", we'd have to resort to something like this:

title = Post.arel_table[:title]
content = Post.arel_table[:content]

With Wharel, you can drop the boilerplate and just use a block:

Post.where { title.matches("foo").and(content.matches("bar")) }

Wharel will map title and content in the block to the appropriate Arel attribute for the column.

Wharel also supports most other query methods, e.g. not:

Post.where.not { title.eq("foo") }

... and order:

Post.order { title.lower }

Wharel also supports select, having, pluck, pick, group and or in the same way.

Now suppose we have another model Comment with a column content, and a Post has_many :comments:

class Post < ApplicationRecord
  has_many :comments

class Comment < ApplicationRecord
  belongs_to :post

Now we want to find all comments which match the title of the comment's post. With standard Arel, you could do this with:

posts = Post.arel_table
comments = Comment.arel_table

Using Wharel, you can pass an argument to blocks to handle this case:

Comment.joins(:post).where { |c| Post.where { |p| c.content.matches(p.title) } }

Much better!


Notice something wrong or a feature missing? Post an issue or create a pull request.


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