How to skip transaction in ActiveRecord for INSERT ONLY statement?

前端 未结 5 1016
孤独总比滥情好
孤独总比滥情好 2020-12-30 05:19

Look at this example:

2.1.3 :001 > Stat.create!
   (0.1ms)  BEGIN
  SQL (0.3ms)  INSERT INTO `stats` (`created_at`, `updated_at`) VALUES (\'2015-03-16 11:         


        
5条回答
  •  独厮守ぢ
    2020-12-30 05:30

    The problem here is that you want to modify behavior for a class-level method. This is inherently not thread-safe, at the very least for concurrent transactions for other Stat objects. A simple workaround would be to flag the instance as not requiring a transaction:

    class Stat < ActiveRecord::Base
      attr_accessor :skip_transaction
    
      def with_transaction_returning_status
        if skip_transaction
          yield
        else
          super
        end
      end
    end
    
    Stat.create! skip_transaction: true
    

    If you are running on a single threaded framework, and therefore aren't concerned with suspending transactions for Stat objects during this time, you can use class level methods and wrap the call like so:

    class Stat < ActiveRecord::Base
      def self.transaction(*args)
        if @skip_transaction
          yield
        else
          super
        end
      end
    
      def self.skip_transaction
        begin
          @skip_transaction = true
          yield
        ensure
          @skip_transaction = nil
        end
      end
    end
    
    Stat.skip_transaction { Stat.create! }
    

提交回复
热议问题