Created
September 4, 2016 10:24
-
-
Save estum/f7c8dab9fa2cb760c2da47be30da4215 to your computer and use it in GitHub Desktop.
Swallow Reader extension for Active Record Has One Through Association
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# = Swallow Reader | |
# | |
# Adds <tt>:swallow</tt> option to <tt>has_one :through</tt> association builder. | |
# When this option set to <tt>true</tt> and through association was loaded, target record will | |
# be readed directly from parent without executing the join query. | |
# | |
# For example: | |
# | |
# class Review < ActiveRecord::Base | |
# belongs_to :song | |
# has_one :artist, through: :song, swallow: true | |
# end | |
# | |
# Review.preload(:song).artist | |
# | |
# Without swallow it executes query: | |
# | |
# SELECT "artists".* FROM "artists" INNER JOIN "songs" ON "artists"."id" = "songs"."artist_id" WHERE "songs"."id" = $1 LIMIT $2 | |
# | |
# With <tt>swallow: true</tt>: | |
# | |
# SELECT "artists".* FROM "artists" WHERE "artists"."id" = $1 LIMIT $2 | |
# | |
module SwallowReader | |
module BuilderHook | |
def valid_options(options) | |
valid = super | |
valid << :swallow if options[:through] | |
valid | |
end | |
end | |
module AssociationMethods | |
def reader(force = false) | |
read_swallow? ? swallow_reader(force) : super | |
end | |
def swallow_reader(force = false) | |
through_association.reader&.public_send(reflection.name, force) | |
end | |
private | |
def through_association | |
@owner.association(options[:through]) | |
end | |
def read_swallow? | |
options[:swallow] && !loaded? && through_association.loaded? | |
end | |
end | |
end | |
ActiveSupport.on_load(:active_record) do | |
ActiveRecord::Associations::Builder::HasOne.singleton_class.prepend(SwallowReader::BuilderHook) | |
ActiveRecord::Associations::HasOneThroughAssociation.prepend(SwallowReader::AssociationMethods) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment