Skip to content

Commit

Permalink
Load associations for all records with the same object_id
Browse files Browse the repository at this point in the history
  • Loading branch information
Etienne Tripier committed Aug 1, 2017
1 parent 3db4563 commit e391746
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 19 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Call `preload` when defining your field:
# Post.includes(:comments, :authors)
preload [:comments, :authors]

# Post.includes(:comments, authors: [:posts, :followers])
preload [:comments, { authors: [:posts, :followers] }]
# Post.includes(:comments, authors: [:followers, :posts])
preload [:comments, { authors: [:followers, :posts] }]

resolve ->(obj, args, ctx) { obj.comments }
end
Expand Down
7 changes: 3 additions & 4 deletions lib/graphql/preload/instrument.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ def instrument(_type, field)
promises << preload(record, sub_association)
end
when Hash
association.each do |sub_association, property|
association.each do |sub_association, nested_association|
promises << preload_single_association(record, sub_association).then do
associated_records = record.public_send(sub_association)

case associated_records
when ActiveRecord::Base
preload(associated_records, property)
preload(associated_records, nested_association)
else
Promise.all(
Array.wrap(associated_records).map do |associated_record|
preload(associated_record, property)
preload(associated_record, nested_association)
end
)
end
Expand All @@ -56,7 +56,6 @@ def instrument(_type, field)
end

private def preload_single_association(record, association)
return Promise.resolve(record) if record.association(association).loaded?
GraphQL::Preload::Loader.for(record.class, association).load(record)
end
end
Expand Down
31 changes: 19 additions & 12 deletions lib/graphql/preload/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ module Preload
class Loader < GraphQL::Batch::Loader
attr_reader :association, :model

def cache_key(record)
record.object_id
end

def initialize(model, association)
@association = association
@model = model
Expand All @@ -13,38 +17,41 @@ def initialize(model, association)

def load(record)
unless record.is_a?(model)
raise TypeError, "loader for #{model.name} can't load associations for #{record.class.name} objects"
raise TypeError, "Loader for #{model} can't load associations for #{record.class} objects"
end

if record.association(association).loaded?
Promise.resolve(record)
else
super
end
return Promise.resolve(record) if association_loaded?(record)
super
end

def perform(records)
preload_association(records)
records.each { |record| fulfill(record, record) }
end

private def association_loaded?(record)
record.association(association).loaded?
end

private def preload_association(records)
if ActiveRecord::VERSION::MAJOR > 3
ActiveRecord::Associations::Preloader.new.preload(records, association)
else
ActiveRecord::Associations::Preloader.new(records, association).run
end

records.each { |record| fulfill(record, record) }
end

private def validate_association
unless association.is_a?(Symbol)
raise ArgumentError, 'association must be a Symbol object'
raise ArgumentError, 'Association must be a Symbol object'
end

unless model < ActiveRecord::Base
raise ArgumentError, 'model must be an ActiveRecord::Base descendant'
raise ArgumentError, 'Model must be an ActiveRecord::Base descendant'
end

return if model.reflect_on_association(association)

raise TypeError, "association :#{association} does not exist on #{model.name}"
raise TypeError, "Association :#{association} does not exist on #{model}"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/preload/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module GraphQL
module Preload
VERSION = '1.0.2'.freeze
VERSION = '1.0.3'.freeze
end
end

0 comments on commit e391746

Please sign in to comment.