AncestryJoins

This gem provides additional ActiveRecord scopes to fetch ancestry records in bulk.

Problem

The ancestry gem only provides instance scopes which when used in iteration causes N+1 query performance issues. For example:

# if we have 100 interesting items, this will run 1 + 100 querys!
Item.where(interesting: true).flat_map{|i| i.ancestors}

Solution

Using this gem will fetch identical results to the flat_map but in a single query.

Item.where(interesting: true).with_ancestors_only

Caveats

Due to the custom SQL select, only Postgres is supported at the moment. More databases can be supported in the future. Look at lib/ancestry_joins.rb to implement scopes for another database.

Usage

IMPORTANT Use the scope last in the chain for good performance, otherwise the ancestry grouping act on the entire table before applying the filter. If you have other models to join against the ancestry, those maybe added after including the ancestry joins.

class Item < ActiveRecord::Base
  has_ancestry
  include AncestryJoins

  has_many :widgets
end

# Get list of Items with red color, their parents regardless of color, and the
# red items or red items ancestors' parents widgets are blue.
Item
  .where(color: 'red')
  .with_ancestors
  .joins(:widgets)
  .merge(Widget.where(color: 'blue'))

Look to the specs for more details.

Installation

Add this line to your application's Gemfile:

gem 'ancestry_joins'

And then execute:

$ bundle

Or install it yourself as:

$ gem install ancestry_joins

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

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

License

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