0

Well, I have a model with a has_many association:

class Foo < ApplicationRecord
  has_many :bars
end

Now, I know that if I call foo.bars it loads all the bars where foo_id is foo.id, right? But I would like to override it, so that I could load bars based on other params..

This answer kinda teaches how to override the << (value) method. But yet, I don't know how to apply it in my case.

How could I do that?? Something like this:

class Foo < ApplicationRecord
  has_many :bars do
    def bars
      self.owner = Bar.where(date: foo.date) #just an example
    end
  end
end

???

Community
  • 1
  • 1
Rafael Costa
  • 1,291
  • 2
  • 13
  • 30
  • Still not really clear what you're trying to do. Do you want the association to be based on, say, `foos.date = bars.date` rather than `foos.bar_id = bars.id`? – mu is too short Jan 17 '17 at 05:31
  • Yeah!! Something like that.. When I call `foo.bars` I want it to return all the bars in a given date instead of all the bars that belongs to `foo`. – Rafael Costa Jan 17 '17 at 11:09
  • Do you really want a formal association then? Maybe you're just looking for a simple method without all the association machinery. – mu is too short Jan 17 '17 at 17:56
  • Well, I see what you're saying, but I would like to use the other methods from an ActiveRecord association. But thinking better about it know, maybe I would have to override most of the other methods as well. Anyways.. I would like to know how to do this just for curiosity.. – Rafael Costa Jan 18 '17 at 22:49

2 Answers2

3

You can set a condition on the has_many attribute like this

has_many :bars, -> { where(active: true) } 

More on that in the guides (section 4.3.3)

Eyeslandic
  • 14,553
  • 13
  • 41
  • 54
  • Well, it does help, thanks!! However, I don't want to extend, because I want to search only the bars with `active: true` not all the bars with `foo_id: foo.id` and that `active: true`. Get me? – Rafael Costa Jan 14 '17 at 21:21
  • Well, not exactly. Can you perhaps update your question with more info. – Eyeslandic Jan 14 '17 at 21:45
0

It sounds like you're asking for a way to override an association getter so that it acts like a simple scope or where query instead — namely, that you want foo.bars to return a set of bars that may or may not belong to foo.

This is a huge red flag.

The whole point of having the #bars association getter method as an instance method of Foo is to return a list of bars related to a single model object. If you want something different, define the behavior somewhere else.

In theory, what you're asking is possible — just take the def bars stanza from your example out of the has_many block and put it on the same level as all your other method definitions. But there's simply no sense in it.

Bar.where and scope are built to do what you're asking about. If you don't want to limit your query to a given Foo, then leave Foo out of it.

Ryan Lue
  • 916
  • 10
  • 29