Skip to content

Instantly share code, notes, and snippets.

@crmaxx
Forked from godfat/eager_cursor.rb
Last active March 21, 2016 13:12
Show Gist options
  • Save crmaxx/df26a96ec0a7f60ea7ed to your computer and use it in GitHub Desktop.
Save crmaxx/df26a96ec0a7f60ea7ed to your computer and use it in GitHub Desktop.
dataset_module do
# User.one_to_one(:auth)
# User.eager_cursor(1000, :auth) do |user|
# user.auth # no additional query
# end
def eager_cursor(rows_per_fetch = 1000, *associations)
cursor = use_cursor(rows_per_fetch: rows_per_fetch)
cursor.each_slice(rows_per_fetch) do |records|
associations.each do |assoc|
refl = model.association_reflection(assoc)
case refl[:type]
when :one_to_one
EagerCursorOneToMany
when :many_to_one
EagerCursorManyToOne
else
fail "Cannot handle: #{refl[:type]}"
end.new(records, refl).load
records.each do |r|
yield(r)
end
end
end
end
EagerCursor = Struct.new(:records, :reflection) do
def load
associations = reflection.associated_class.where(association_key => records.map(&record_key)).all
records.each do |r|
if (i = associations.find_index(&method(:find).curry[r]))
a = associations.delete_at(i)
r.associations[reflection[:name]] = a
end
end
records
end
private
def find(record, association)
record.public_send(record_key) == association.public_send(association_key)
end
end
class EagerCursorOneToMany < EagerCursor
private
def association_key
reflection[:key]
end
def record_key
reflection.primary_key
end
end
class EagerCursorManyToOne < EagerCursor
private
def association_key
reflection.primary_key
end
def record_key
reflection[:key]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment