Skip to content

Commit

Permalink
Make after_load association callbacks take effect when eager loading …
Browse files Browse the repository at this point in the history
…via eager

Previously, they did not take affect when eager loading.  They still
do not take affect when eager loading via eager_graph, but now they
take affect when eager loading via eager, since support was easy to
add.  They are supported outside the :eager_loader, so even if you
define your own eager_loader, they still get run correctly.  This is
a slight breakage of backwards compatibility, but it's definitely the
desired behavior in most circumstances.
  • Loading branch information
jeremyevans committed Oct 29, 2008
1 parent 1cfb97e commit 915ccc1
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
=== HEAD

* Make after_load association callbacks take effect when eager loading via eager (jeremyevans)

* Add a :uniq association option to many_to_many associations (jeremyevans)

* Support using any expression as the argument to Symbol#like (jeremyevans)
Expand Down
2 changes: 1 addition & 1 deletion lib/sequel_model/associations.rb
Expand Up @@ -88,7 +88,7 @@ def all_association_reflections
# after a new item is added to the association.
# - :after_load - Symbol, Proc, or array of both/either specifying a callback to call
# after the associated record(s) have been retrieved from the database. Not called
# when eager loading (see the :eager_loader option to accomplish it when eager loading).
# when eager loading via eager_graph, but called when eager loading via eager.
# - :after_remove - Symbol, Proc, or array of both/either specifying a callback to call
# after an item is removed from the association.
# - :allow_eager - If set to false, you cannot load the association eagerly
Expand Down
5 changes: 4 additions & 1 deletion lib/sequel_model/eager_loading.rb
Expand Up @@ -381,7 +381,10 @@ def eager_load(a)
end
end

reflections.each{|r| r[:eager_loader].call(key_hash, a, eager_assoc[r[:name]])}
reflections.each do |r|
r[:eager_loader].call(key_hash, a, eager_assoc[r[:name]])
a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])}
end
end

# Build associations from the graph if #eager_graph was used,
Expand Down
9 changes: 5 additions & 4 deletions spec/integration/eager_loader_test.rb
Expand Up @@ -228,7 +228,6 @@ class ::Firm < Sequel::Model
firms.each{|firm| firm.associations[:invoices] = []}
Invoice.eager_graph(:client).filter(:client__firm_id=>id_map.keys).all do |inv|
id_map[inv.client.firm_id].each do |firm|
inv.client.associations[:firm] = inv.associations[:firm] = firm
firm.associations[:invoices] << inv
end
end
Expand All @@ -255,20 +254,22 @@ class ::Invoice < Sequel::Model
:after_load=>(proc do |inv, firm|
# Delete the cached associations from firm, because it only has the
# client with this invoice, instead of all clients of the firm
inv.associations[:client] = firm.associations.delete(:clients).first
if c = firm.associations.delete(:clients)
firm.associations[:invoice_client] = c.first
end
inv.associations[:client] ||= firm.associations[:invoice_client]
end), \
:eager_loader=>(proc do |key_hash, invoices, associations|
id_map = {}
invoices.each do |inv|
inv.associations[:firm] = nil
inv.associations[:client] = nil
(id_map[inv.client_id] ||= []) << inv
end
Firm.eager_graph(:clients).filter(:clients__id=>id_map.keys).all do |firm|
# Delete the cached associations from firm, because it only has the
# clients related the invoices being eagerly loaded, instead of all
# clients of the firm.
firm.associations.delete(:clients).each do |client|
firm.associations[:clients].each do |client|
id_map[client.pk].each do |inv|
inv.associations[:firm] = firm
inv.associations[:client] = client
Expand Down
10 changes: 10 additions & 0 deletions spec/sequel_model/eager_loading_spec.rb
Expand Up @@ -455,6 +455,16 @@ def fetch_rows(sql)
MODEL_DB.sqls.length.should == 4
end

it "should respect :after_load callbacks on associations when eager loading" do
EagerAlbum.many_to_one :al_band, :class=>'EagerBand', :key=>:band_id, :after_load=>proc{|o, a| a.id *=2}
EagerAlbum.one_to_many :al_tracks, :class=>'EagerTrack', :key=>:album_id, :after_load=>proc{|o, os| os.each{|a| a.id *=2}}
EagerAlbum.many_to_many :al_genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :after_load=>proc{|o, os| os.each{|a| a.id *=2}}
a = EagerAlbum.eager(:al_band, :al_tracks, :al_genres).all.first
a.should == EagerAlbum.load(:id => 1, :band_id => 2)
a.al_band.should == EagerBand.load(:id=>4)
a.al_tracks.should == [EagerTrack.load(:id=>6, :album_id=>1)]
a.al_genres.should == [EagerGenre.load(:id=>8)]
end
end

describe Sequel::Model, "#eager_graph" do
Expand Down

0 comments on commit 915ccc1

Please sign in to comment.