jpw
jpw

Reputation: 19247

Rails 3, confused about 'before_create :some_method' ... WHEN does some_method do its thing?

we have model helper (used by several different models) called set_guids that sets self.theguid to a random string. Been using it for a long time, we know it works.

in a new model 'Dish' we created, we have

before_create :set_guids    (NOTE: no other before/after/validation, just this)

def do_meat_dish
  ( this is invoked by @somemeat.do_meat_dish in the Dish contoller )
  ( it manipulated the @somemeat object using self.this and self.that, works fine)

  ( THEN sometimes it creates a new object of SAME MODEL type )
  ( which is handled differently) 
    @veggie = Dish.new
    @veggie.do_veggie_dish
end

def do_veggie_dish
  recipe_str = "add the XXXX to water"
  recipe_str.gsub!("XXXX", self.theguid)  *** the PROBLEM: self.theguid is nil 
end

as soon as we execute veggie = Dish.new shouldn't veggie.theguid be initialized?

Note we have not saved the new object yet... but the before_create should still have done its thing, right?

it is something to do with create a new instance of a model inside a method for the same model?

is it something with using @ for the variables?

Additional note: if we comment out the line trying to access self.theguid everything else works fine ... it's ONLY the value (supposedly) set by the before_create set_guids that is nil instead of being a guid.

Upvotes: 0

Views: 1682

Answers (1)

khelll
khelll

Reputation: 24000

before_create is called only before the object is saved to the database the first time. That's why you get nil.

I suggest that you use after_initialize callback instead. Be careful though, since after_initialize will be called whenever the document is new or loaded from the db, that way you will have new guids every time you get the document, which is not what you want. So I suggest you do something like:

def set_guids 
  return unless theguid.nil?
  .....
end

As another solution, if you don't want to change the after_create callback above, you can do something like:

def theguid
  super || set_guids
end

That should let you go also.

Upvotes: 2

Related Questions