In Rails, how can I retrieve the object on a belongs_to association, without going through the database?
Asked Answered
C

2

5

Consider the following setup:

class Parent < ActiveRecord::Base
  has_many :children
end

class Child < ActiveRecord::Base
  belongs_to :parent
end

And this console session:

>> p = Parent.find 41
>> p.some_attr = 'some_value'
>> c = p.children.build
>> c.parent

By watching my log files, I can see that c.parent is querying the db for the parent object. I want instead to access the existing in-memory object (p), because I need access to the parent's some_attr value, which is not yet stored in the database. Is there any way of doing this? c.parent(force_reload=false) doesn't get me there.

Columbuscolumbyne answered 30/6, 2010 at 19:56 Comment(0)
B
6

You could use :inverse_of to set it. Read more about it here.

Bastian answered 26/8, 2010 at 2:59 Comment(1)
Yes, :inverse_of was developed precisely to fit this need.Columbuscolumbyne
K
1

ActiveRecord doesn't endeavor to guarantee that in-memory objects for the same database objects are all the same. This is something that DataMapper does guarantee.

I realize your example is probably simplified in order to ask your question, but just from a naive look at it -- why don't you just use p instead of c.parent?

Another possibly helpful suggestion, save the update to parent to the db:

p = Parent.find 41

# do this...
p.some_attr = 'some_value'
p.save

# OR this...
p.update_attribute(:some_attr, 'some_value')

c = p.children.build
c.parent

I'm not sure if c.parent(false) ("don't reload from the db") will do the trick here, since it's a fresh Child object. But you can try that too.

Kvass answered 30/6, 2010 at 20:13 Comment(2)
You are right about the example being simplified - in real life I am working with a validation scenario in which the child's validity depends on attributes of the parent (actually, attributes of a sibling object collection). So in the child object's validation code I need to get to the parent as it exists in memory, with all of the attributes that just got assigned/updated when the html form was submitted, and not the stale version that is sitting out in the db. I am using accepts_nested_attributes_for :children, so I know everything is set up as I need it in memory.Columbuscolumbyne
You can do the whole thing in a transaction -- that way you can save the parent, then check the validation, if validation fails, you roll back.Kvass

© 2022 - 2024 — McMap. All rights reserved.