Search code examples
ruby-on-railsrubyruby-on-rails-4associationsafter-save

Rails 4 Create Associated Object on Save


How can I create multiple associated objects automatically just after I save a new primary object?

For example

In Rails 4, I have three objects: Businesses, Budgets, and Categories.

#app/models/business.rb
class Business < ActiveRecord::Base
   #attrs id, name
   has_many :budgets
end

#app/models/budget.rb
class Budget < ActiveRecord::Base
   #attrs id, business_id, department_id, value
   belongs_to :business 
   belongs_to :category
end

#app/models/category.rb
class Category < ActiveRecord::Base
   #attrs id, name
   has_many :budgets
end

When I create a new Business, after saving the new Business, I would like to atomically create a Budget for each Category and give it value of $0. This way, when I go to show or edit a new Business, it will already have the associated Categories and Budgets, which can then be edited. Thus, upon creating a new Business, multiple new Budgets will be created, one for each Category, each with the value of 0.

I read this article: Rails 3, how add a associated record after creating a primary record (Books, Auto Add BookCharacter)

And I am wondering if I should use the after_create callback in the Business model and have the logic then exist in the Budgets controller (not exactly sure how to do this) or if I should add logic to the businesses_controller.rb in the 'new' call with something similar to:

@business = Business.new
@categories = Category.all
@categories.each do |category|
      category.budget.build(:value => "0", :business_id => @business.id)
end

Solution

  • I ended up adding the logic to the create method in the Business controller to loop through all Categories and create a budget just after save. Note that I was lazy and didn't put in any error handling. :

      def create
        @business = Business.new(params[:business])
    
        @results = @business.save
    
        @categories = Categories.all
    
        @categories.each do |category|
          category.budgets.create(:amount => "0", :business_id => @business.id)
        end
    
    
        respond_to do |format|
          ...
        end
      end