Rails nil association in after_initialize

I have two models with associations from one to many. I want to set the default value for the child model when initializing based on some parent state. This includes having an after_initialize callback for a child who needs to access the parent through the belongs_to association. The problem is that when I instantiate the child using the assembly method, the association with the parent is zero in the after_initialize callback. Is this expected behavior? I'm on the rails 3.0.6

Toy example:

class Merchant < ActiveRecord::Base has_many :products end class Product < ActiveRecord::Base belongs_to :merchant after_initialize :set_default_value def set_default_value if merchant.state self.foo = some_value else self.foo = some_other_value end end end 

And in the controller:

 product = merchant.products.build 

In the set_default_value call, the merchant is zero, although it seems that this should not be.

+8
ruby-on-rails ruby-on-rails-3
source share
3 answers

I would modify the code as follows:

 class Product < ActiveRecord::Base ... def set_default_value(state = merchant.state) if state self.foo = some_value else self.foo = some_other_value end end end 

Then change your caller to:

 product = merchant.products.build(:state => merchant.state) 

In addition, I found that after_initialize callbacks will be slow. So another option is to move the logic to the constructor for the product.

 product = merchant.products.build(:foo => merchant.state ? some_value : some_other_value) 

It also eliminates the violation of the law of Demeter from the code (i.e. the Product does not need to know / care about what the seller’s condition is).

+1
source share

I am on rails 2.3 and I can confirm that

 product = merchant.products.build 

will not return the correct merchant_id association in the after_initialize callback

but I found that it will work correctly with

 product = merchant.products.new 

I think this has been fixed with this commit (I really don't know, I'm not very familiar with the git workflow):

https://github.com/rails/rails/issues/1842

Since on rails 3.1.11 it works for both build and new

0
source share

You are inverse_of looking for inverse_of

 has_many :products, inverse_of: :merchant 
0
source share

All Articles