Home Eager loading sibling records without including self
Reply: 1

Eager loading sibling records without including self

jordanm
1#
jordanm Published in 2017-11-13 18:26:55Z

For serialization I want to include an array of sibling records which shares a common foreign key. I currently have the following:

class Foo < ActiveRecord::Base
  has_many :other_instances,
           source: :foo,
           class_name: 'Foo',
           foreign_key: 'event_id',
           primary_key: 'event_id'

When used in an include, it produces the following queries:

  Foo Load (0.2ms)  SELECT  "foo".* FROM "foo" WHERE "foo"."id" = $1 LIMIT 1  [["id", 21138]]
  Foo Load (0.4ms)  SELECT "foo".* FROM "foo" WHERE "foo"."event_id" IN (11451)

This mostly works, but the issue is that Foo.other_instances includes itself. Is there any way to exclude that additional record in rails? The expected includes would look something like this:

  Foo Load (0.4ms)  SELECT "foo".* FROM "foo" WHERE "foo"."event_id" IN (11451) AND "foo"."id" NOT IN (21138)

Update:

Attempting to make the condition instance dependent as in @spikermann's results in the following:

Code:

has_many :other_instances,
         source: :foo,
         class_name: 'Foo',
         foreign_key: 'event_id',
         primary_key: 'event_id', 
         ->(foo) { where.not(id: foo.id) }

Called with:

Foo.includes(:other_instances).find(21138)

Result:

DEPRECATION WARNING: The association scope 'other_instances' is instance dependent (the scope block takes an argument). Preloading happens before the individual instances are created. This means that there is no instance being passed to the association scope. This will most likely result in broken or incorrect behavior. Joining, Preloading and eager loading of these associations is deprecated and will be removed in the future. (called from check_preloadable! at /home/jordan/prog/knotweed/vendor/bundle/gems/activerecord-4.2.7.1/lib/active_record/reflection.rb:362)
NoMethodError: undefined method `id' for nil:NilClass
spickermann
2#
spickermann Reply to 2017-11-13 18:54:43Z

What about adding a scope:

has_many :other_instances,
         source: :foo,
         class_name: 'Foo',
         foreign_key: 'event_id',
         primary_key: 'event_id', 
         ->(foo) { where.not(id: foo.id) }
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.330994 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO