delegate_cached is a Ruby gem to easily cache delegated attributes on an ActiveRecord model, and have the cache updated when the delegated value changes.
One regret I have from my Intridea days is that I was so busy running the business that I rarely had time to contribute in meaningful ways to open-source projects. Sure, I pitched in a commit here or there on various projects, but largely my contributions involved clearing the schedule of our team’s engineers enough so they could work on their own open-source projects.
So, it is with great pleasure that, at long last, I release my first
open-source Ruby gem:
As with most open-source contributions, this gem came about in response to a pain point I was having on an existing project. After installing the bullet gem and tracking down a lot of N+1 queries, I found myself frequently having to include a rarely-touched model.
Company model references an
IndustryCompanyList (names have been changed
to protect the innocent), which is a occasionally-updated “official” list of
companies from an external industry source.
OfficialCompanyList has a
attribute we would like to display as the Company name, so we delegate to
OfficialCompanyList as below.
This works well. With any instance of
Company, we can call
we get the value through the delegated association.
IndustryCompanyList must then, however, be included every time
is referenced to avoid the N+1 query issue. Storing the value from
IndustryCompanyList in a column on
Company would prevent this issue, but
there would need to be a process to prevent the data from going stale when
IndustryCompanyList values are updated. Enter,
We start with two classes in a
has_many relationship, where
Hiker class has a
As in the case above, this works well. We can call
retrieve the delegated
name value from the associated
Hiker. But if the
hiker’s name rarely changes, we could instead cache it on the
to avoid having to touch the
Hiker model each time we want to access the
This can now be easily accomplished with
delegate_cached using virtually the
same syntax as
ThruHike is now cacheing the value, you would need to create and run a
migration adding a
name column to the
What you now get by using
thru_hike.nameis nil, it updates itself with the delegated value. Subsequent accesses will return the cached value.
- When the
thru_hikeupdates the value of its
before_savecallback updates the
thru_hike.nameto the new value.
- When the associated
Hikerupdates its name, an
after_savecallback updates the value in
There’s still more work to be done on
delegate_cached to make it backwards
compatible with Rails 4.X, and other features I’m interested in adding. I
welcome bug reports, feedback, suggested improvements, and any other comments
on the Github site below.