【问题标题】:Rails nested transactionsRails 嵌套事务
【发布时间】:2016-03-01 01:17:57
【问题描述】:

我正在尝试制作 rails 应用程序,但我遇到了这个问题。 我有嵌套交易,虽然他们一直在工作。但是,我发现它们不能正常工作。

这里是用户服务

    class UserService
    def self.reduce_balance!(user, delta, attachmentable)
      ActiveRecord::Base.transaction do
        user.balance.amount -= delta
        balance_decrease = BalanceDecrease.new(user: user, attachmentable: attachmentable, balance_before: user.balance.amount_was, amount: delta)
        user.balance.save!
        balance_decrease.save!
      end
      return true
    end
    end

有游戏服务

    class GameService
      def self.take_spot(user, spot)
        if UserService.have_enough_money? user, game.spot_price
          begin
            ActiveRecord::Base.transaction do
              spot.free = false
              spot.user = user
              spot.save!
              UserService.reduce_balance!(user, game.spot_price, spot)
              return res = {success: true, json: spot, status: 200}
            end
          rescue => e
            return res = {json: {error: 1, error_message: "Something gone wrong"}, status: 500}
          end
        else
          return res = {json: {error: 1, error_message: "You don't have enough money"}, status: 400}
        end
      end
    end

我有我的控制器

    def update
      @res = GameService.take_spot current_user, @spot
      return render json: @res[:json], status: @res[:status] unless @res[:success]
    end

不知何故,1700 个查询中有 1 个出错了:已购买现货且余额并未减少。 This is picture of json

json文件(下图):

{
"id": 1759,
"type": "BalanceDecrease",
"balance_before": "950.00",
"amount": "10.00",
"spot": {
"id": 1965,
"number": 7,
"free": false,
"game": {
"id": 19,
"name": "M249 | Блокировка",
"img_url": "(img url)",
"stattrak": false,
"spot_price": "10.00",
"state": "ended",
"created_at": "2015-11-26T23:20:28.081+03:00",
"updated_at": "2015-11-26T23:20:59.406+03:00"
},
"created_at": "2015-11-26T23:20:28.087+03:00",
"updated_at": "2015-11-26T23:20:57.270+03:00"
}
},
{
"id": 1758,
"type": "BalanceDecrease",
"balance_before": "950.00",
"amount": "10.00",
"spot": {
"id": 1964,
"number": 6,
"free": false,
"game": {
"id": 19,
"name": "M249 | Блокировка",
"img_url": "(img url)",
"stattrak": false,
"spot_price": "10.00",
"state": "ended",
"created_at": "2015-11-26T23:20:28.081+03:00",
"updated_at": "2015-11-26T23:20:59.406+03:00"
},
"created_at": "2015-11-26T23:20:28.087+03:00",
"updated_at": "2015-11-26T23:20:57.282+03:00"
}
}

我有 10 美元的 DigitalOcean 水滴。会不会是问题?

【问题讨论】:

    标签: ruby-on-rails database postgresql ruby-on-rails-4 transactions


    【解决方案1】:

    ActiveRecord::Rollback 不会传播到包含事务块之外,因此父事务不会收到嵌套在子事务中的异常。

    为确保父事务收到回滚,您必须将requires_new: true 选项添加到子事务。

    查看this articledocs 了解更多详情。

    因此,将其应用于您的案例,您应该拥有user_service.rb,如下所示:

    class UserService
      def self.reduce_balance!(user, delta, attachmentable)
        ActiveRecord::Base.transaction(requires_new: true) do
          # code omitted
        end
      end
    end
    

    【讨论】:

      【解决方案2】:

      您的问题源于您使用交易的方式。

      当你嵌套它们时,你必须使用requires_new: true

      ActiveRecord::Base.transaction do 
        ActiveRecord::Base.transaction(requires_new: true) do 
      
        end
      end
      

      解释得很好in the doc

      顺便说一句,总是使用requires_new: true 并没有什么坏处。


      旁注,您似乎使用了服务对象并将它们链接起来,可能是this would interest you

      【讨论】:

        猜你喜欢
        • 2016-09-09
        • 2014-12-12
        • 2016-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-08
        • 2016-06-30
        • 2018-10-07
        相关资源
        最近更新 更多