ruby-on-railscallback

Rails callback, create a record after creating or updating an associated record


Can I, or should I, use a callback to create an associated record in Rails? Also, if either record creation or update fails will both records not be saved in the database?

The idea behind this solution is to DRY up the code.

If so, should I use after_save or something else? If I should use after_save, is the example below sufficient or do I need to raise an error or do something else?

I am aware of gems like papertrail that will do something like this but this is not the solution we need.

Example:

class Fruit < ApplicationRecord

end


class Apple < ApplicationRecord
  after_save :create_fruit
 
  def create_fruit
     Fruit.create!(item_id: self.id)
  end
end

It seems that there will be a rollback and both records will not be saved based on this answer and here. I do believe this answer may help also but still think I need to ask this question at the moment. Will my example rollback if there is an issue with either record update or creation?


Solution

  • You don't need a callback.

    If you just setup an association between the two models you can create both at once:

    class Fruit < ApplicationRecord
      belongs_to :item, polymorphic: true
    end
    
    class Apple < ApplicationRecord
      has_one :fruit, as: :item
    end
    
    apple = Apple.new
    apple.build_fruit
    apple.save
    

    This will create both in a transaction. If you want to fire the validations on Fruit you can use validates_associated:

    class Apple < ApplicationRecord
      has_one :fruit, as: :item
      validates_assocatiated :item
    end
    

    Sure you could wrap this process into a callback - but just do it explicitly for now and refactor when and if you actually need it as callbacks come with their own set of drawbacks.