Rails after_initialize only on "new"

Tyler DeWitt picture Tyler DeWitt · Mar 7, 2012 · Viewed 39k times · Source

I have the following 2 models

class Sport < ActiveRecord::Base
  has_many :charts, order: "sortWeight ASC"
  has_one :product, :as => :productable
  accepts_nested_attributes_for :product, :allow_destroy => true
end

class Product < ActiveRecord::Base
  belongs_to :category
  belongs_to :productable, :polymorphic => true
end

A sport can't exist without the product, so in my sports_controller.rb I had:

def new
  @sport = Sport.new
  @sport.product = Product.new
...
end

I tried to move the creation of the product to the sport model, using after_initialize:

after_initialize :create_product

def create_product
 self.product = Product.new
end

I quickly learned that after_initialize is called whenever a model is instantiated (i.e., from a find call). So that wasn't the behavior I was looking for.

Whats the way I should be modeling the requirement that all sport have a product?

Thanks

Answer

bostonou picture bostonou · Mar 8, 2012

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