AASM does not trigger ActiveRecord::Rollback

575 Views Asked by At

I have approve event enum in Booking model. I have a before_validation in approve

in my model/booking.rb I added custom validation

    include AASM

    before_validation :item_availability, if: :approved?

    enum status: [:pending, :approved, :rejected, :on_loan, :returned]

    aasm column: :status, enum: true do

       state :pending, initial: true
       state :approved
       state :rejected
       state :on_loan
       state :returned    

       event :approve do
         transitions from: :pending, to: :approved
       end

       event :reject do
         transitions from: :pending, to: :rejected
       end

       event :on_loan do
         transitions from: :approved, to: :on_loan
       end

       event :returned do
         transitions from: :on_loan, to: :returned
       end

  end


  private

  def item_availability
    if item.quantity.to_f < quantity.to_f
      errors.add(:base, "Not enough quantity for #{item.name} only #{item.quantity} left")
      false
    end
  end

and in my controller, I'm calling the service

 @service = Manage::BookingApprovalService.new({booking: @booking})
 @service.run

app/services/manage/booking_approval_service

class Manage::BookingApprovalService < BaseService

  attr_accessor :booking

  def run
    Booking.transaction do
      booking.approve! // I confirmed that I'm getting the false here 
      booking.item.decrement!(:quantity, booking.quantity)
      BookingsMailer.send_approval(booking).deliver_now
    end
  end

end

I'm getting false when I debug the booking.approve! because the quantity I have in booking is greater than the item quantity.

But from the service. the decrement! and send_approval mail is still invoking.

Why does the service doesn't rollback if I'm getting false from booking.approve!

1

There are 1 best solutions below

0
On

The transaction block will rollback only if you raise an exception.

def run
  Booking.transaction do
    fail(ActiveRecord::Rollback) unless booking.approve! 
    booking.item.decrement!(:quantity, booking.quantity)
    BookingsMailer.send_approval(booking).deliver_now
  end
end

Docs: https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html