1

Table structure:

Bar:
  a_id
  b_id
  attr1
  attr2
  ...

Foo:
  id
  a_id
  b_id
  ...

Models:

class Bar < ApplicationRecord
end

class Foo < ApplicationRecord
  belongs_to :bar, lambda { |foo|
    unscope(:where).where(
      a_id: foo.a_id,
      b_id: foo.b_id
    )
  }

  def bar_working
    Bar.find_by(
      a_id: a_id,
      b_id: b_id
    )
  end
end

Calling Foo.find(1).bar yields nil. Calling Foo.find(1).bar_working yields the associated object. Why is the scope not executed when I call the belongs_to association?

This works perfectly fine on a has_many association, just can't get it to work on the belongs_to.

I am running Rails 5.2.2.

Sources:

fgblomqvist
  • 2,244
  • 2
  • 32
  • 44
  • What's the SQL query when you try to get that association? – arieljuod Apr 09 '19 at 19:12
  • @arieljuod no SQL query is executed when I call that association (looking in the Rails debug log). – fgblomqvist Apr 09 '19 at 19:13
  • What's on `Foo.find(1).bar_id`? – arieljuod Apr 09 '19 at 19:15
  • @arieljuod that method won't exist since there is no column named bar_id. Foo is associated to Bar through columns x_id and y_id that together identify a unique row in Bar. – fgblomqvist Apr 09 '19 at 19:18
  • Show your real code, your code example does not reflect what you say. Also show your tables. I'm not sure `belongs_to` scopes does what you are trying to achieve. – arieljuod Apr 09 '19 at 19:20
  • @arieljuod I updated the question according to my comments. – fgblomqvist Apr 09 '19 at 19:29
  • The second link you show is a `has_many` relationship, not a `belongs_to`. The docs on `belongs_to` association does name scopes but as a way to filter records but it does not say `bar_id` would be optional. Also, your class method and your scope doesn't even do the same thing, one would return a collection and the other only one record. Personally I wouldn't use `belongs_to` for your requirement, I don't see any benefit (you wouldn't be able to use `incudes`, `joins`, etc). You could use a `has_many` and add `limit(1)` on the scope maybe, but doesn't look like a good practice. – arieljuod Apr 09 '19 at 20:08
  • @arieljuod Correct about the second link, but according to the second link (like you noticed) it should work for `belongs_to` as well. Obviously it pre-sets the `bar_id` but I'd expect `unscope` to remove that. Maybe it doesn't. No SQL is executed no matter what. And yes, true that they don't do the exact same thing, but again, I would still expect the `belongs_to` to work according to what they say in the docs. So to summarize: based on what you're saying, it sounds like either their docs or their code are incorrect. So yeah, for now I'll just go with the method then (like you suggested). – fgblomqvist Apr 09 '19 at 20:22
  • I don't think the doc is wrong, it supports a scope to scope the lookup of the associated object (maybe the foreign_key is not uniq), I just don't think it works the way you want it to work. Maybe if you set `foreign_key: :a_id` then you can scope by the other column. – arieljuod Apr 09 '19 at 21:13

0 Answers0