Jump to content

The ultimate community for Ruby on Rails developers.


Photo

Callbacks on has_many :through

activerecord

  • Please log in to reply
5 replies to this topic

#1 steft

steft

    Passenger

  • Members
  • 3 posts

Posted 10 September 2013 - 02:52 PM

Hi,
I've been struggling with some callbacks not working as expected.
 
Let's say I have 3 models in a has_many :through relationship => Container has many Items through ContainerItem.

ContainerItem has a callback on after_create that triggers something on Container.
For the sake of simplicity let's say it just updates a field:

  after_create :update_container

  private
    def update_container
        container.update_attribute(:title, "Updated")
    end

The following code snippet shows a weird behavior.
The callback is triggered but the referenced Container still has the old title:

Loading development environment (Rails 3.2.14)
2.0.0-p247 :001 > c = Container.create :title => "C1"
...
2.0.0-p247 :002 > c.container_items
...
 => []
2.0.0-p247 :003 > c.container_items.create item: Item.first, quantity: 5
...
   (0.2ms)  UPDATE "containers" SET "title" = 'Updated', "updated_at" = '2013-09-10 14:32:06.925627' WHERE "containers"."id" = 3
   (1.8ms)  commit transaction
...
2.0.0-p247 :005 > c.title
 => "C1" <<<< Wrong!
...
2.0.0-p247 :009 > Container.find 3
  Container Load (0.2ms)  SELECT "containers".* FROM "containers" WHERE "containers"."id" = ? LIMIT 1  [["id", 3]]
 => #<Container id: 3, title: "Updated", created_at: "2013-09-10 14:31:54", updated_at: "2013-09-10 14:32:06">

Any ideas on what happens here?
 
Thanks!



#2 Rowel

Rowel

    Controller

  • Members
  • 109 posts

Posted 10 September 2013 - 03:55 PM

I think the c.title answer of "C1" is correct and is the expected behavior.  (obviously, that's what the console gave us.) 

 

after_create is only fired/executed when the record is first created, I think. 

 

maybe you need to use after_save ?  



#3 steft

steft

    Passenger

  • Members
  • 3 posts

Posted 10 September 2013 - 04:59 PM

Hi Rowel,

I should have stated more clearly that the after_create is on ContainerItem.rb and it's triggered correctly (look at the last line).

 

Thanks!



#4 Rowel

Rowel

    Controller

  • Members
  • 109 posts

Posted 10 September 2013 - 05:09 PM   Best Answer

try this in your console...  after you do this 

c.container_items.create item: Item.first, quantity: 5

do a 

c.reload 

That will force the rails console to re-read the database... if the underlying record in the database changed, it will be reflected. 


  • Ohm likes this

#5 Ohm

Ohm

    Guard

  • Members
  • 179 posts
  • LocationCopenhagen

Posted 10 September 2013 - 05:21 PM

Like Rowel just pointed out, the c you have which gives you C1 is actually the same c from before, from memory.

 

You need to reload it from the database in order to see the changes that has happened to it.


  • Rowel likes this

Blog: http://ohm.sh | Twitter: madsohm


#6 steft

steft

    Passenger

  • Members
  • 3 posts

Posted 11 September 2013 - 08:08 AM

Yeah, I understand that c holds the old version, but I hoped for a way to automatically force a reload...

Anyway, as far as I can tell there's no way to do it.

I'll use reload.

 

Thank you, both!







Also tagged with one or more of these keywords: activerecord

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users