Rails after_initialize only on "new"
Solution 1:
Putting the logic in the controller could be the best answer as you stated, but you could get the after_initialize
to work by doing the following:
after_initialize :add_product
def add_product
self.product ||= Product.new
end
That way, it only sets product if no product exists. It may not be worth the overhead and/or be less clear than having the logic in the controller.
Edit: Per Ryan's answer, performance-wise the following would likely be better:
after_initialize :add_product
def add_product
self.product ||= Product.new if self.new_record?
end
Solution 2:
Surely after_initialize :add_product, if: :new_record?
is the cleanest way here.
Keep the conditional out of the add_product function
Solution 3:
If you do self.product ||= Product.new
it will still search for a product every time you do a find
because it needs to check to see if it is nil or not. As a result it will not do any eager loading. In order to do this only when a new record is created you could simply check if it is a new record before setting the product.
after_initialize :add_product
def add_product
self.product ||= Product.new if self.new_record?
end
I did some basic benchmarking and checking if self.new_record?
doesn't seem to affect performance in any noticeable way.
Solution 4:
Instead of using after_initialize
, how about after_create
?
after_create :create_product
def create_product
self.product = Product.new
save
end
Does that look like it would solve your issue?
Solution 5:
It looks like you are very close. You should be able to do away with the after_initialize call altogether, but first I believe if your Sport model has a "has_one" relationship with :product as you've indicated, then your Product model should also "belong_to" sport. Add this to your Product model
belongs_to: :sport
Next step, you should now be able to instantiate a Sport model like so
@sport = @product.sport.create( ... )
This is based off the information from Association Basics from Ruby on Rails Guides, which you could have a read through if I am not exactly correct