Rails eager_load, includes, preload can break when changing table or association names. These breaking changes are often discovered in production due to the tricky nature of testing the existence of all the associations listed in the includes. Proper testing is error prone because it requires that all of the listed associations are built during the tests. This gem makes it trivial to test that the associations exist so that you can quickly find the includes to fix when refactoring data models.
Add this line to your application's Gemfile:
gem 'eagerbeaver'And then execute:
$ bundle
Or install it yourself as:
$ gem install eagerbeaver
The constructor takes the model as the first parameter and the includes array as the second parameter:
EagerBeaver.new(MyModel, [:association1, :association2, assoc3: { foo: :bar }])
The instance has one public method, .errors, which returns an array of error messages describing unknown associations.
Imagine we have the following class:
class Lease < ActiveRecord::Base
has_many :lease_terms
has_many :spaces, through: :lease_terms
belongs_to :tenant
endwith the corresponding controller:
class LeasesController < ApplicationController
def index
leases = Lease.all.includes(self.class.lease_includes)
# do some stuff
end
def self.lease_includes
[
:lease_terms,
:spaces,
:tenant,
:foobar
]
end
endWe can ensure that our lease_includes is valid by testing it:
describe LeasesController do
describe 'includes' do
it 'is valid' do
expect(EagerBeaver.new(Lease, LeasesController.lease_includes).errors).to be_empty
end
end
endThis expectation would fail, because .errors will return ['foobar is not an association of Lease'].
EagerBeaver works with nested associations that are aliased with source and class_name as well.
class Lease < ActiveRecord::Base
has_many :targets, class_name: 'right'
has_one :primary_account, through: :targets, source: :account
end
class Right < ActiveRecord::Base
belongs_to :account
belongs_to :lease
belongs_to :space
belongs_to :floor
has_many :lease_terms
end
class Account < ActiveRecord::Base
has_many :properties
end
describe Lease do
describe 'includes' do
let!(:includes) do
[
{ targets: [:space, :floor] },
{ primary_account: :properties }
]
end
it 'is valid' do
expect(EagerBeaver.new(Lease, includes).errors).to be_empty # success!
end
end
endThe gem is available as open source under the terms of the MIT License.