简体   繁体   English

红宝石在铁轨上。 堆栈级别太深错误

[英]ruby on rails. stack level too deep error

stack level too deep error crashed my app. 堆栈级别太深错误导致我的应用崩溃。 I have a deposit model with two rows: income and cashout. 我有两行存款模型:收入和提款。 This two rows modified by after_create callbacks in income and cashout models. 这两行由收入和提现模型中的after_create回调修改。 In cashout model I want to use a before_create callback for validate a balance of deposit (deposit balance must be greater or equal to 0 after creating cashout) and receiving an error: SystemStackError in CashoutsController#create. 在Cashout模型中,我想使用before_create回调来验证存款余额(创建Cashout后存款余额必须大于或等于0)并收到错误:CashoutsController#create中的SystemStackError。

ps: Income callback work fine. ps:收入回调工作正常。

Codes: 代码:

deposit.rb deposit.rb

class Deposit < ActiveRecord::Base
    belongs_to :user
    has_many :incomes
    has_many :cashouts
end

schema.rb schema.rb

... ...

  create_table "deposits", force: true do |t|
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.decimal  "income",     precision: 12, scale: 2
    t.decimal  "cashout",    precision: 12, scale: 2, default: 0.0
  end

cashout.rb cashout.rb

class Cashout < ActiveRecord::Base
    belongs_to :deposit
    validates :deposit_id, :order_sum, presence: true
    validates :order_sum, numericality: true
    validates :order_sum, numericality: { greater_than_or_equal_to: 0}
    before_create :validate_order #before_save crashed too
    after_create :update_deposit_cashout # working fine

    private

    def validate_order
        @deposit = self.deposit
        @income = @deposit.income
        @cashout = self.order_sum
        if @income - @cashout >= 0
            self.save
        else
            !self.save
        end
    end

    def update_deposit_cashout
        @deposit = self.deposit
        @deposit.update_attributes(:cashout => @cashout + self.order_sum)
    end
end

cashouts_controller.rb cashouts_controller.rb

class CashoutsController < ApplicationController
  before_action :signed_in_user, only: [:create]

  def new
    @cashout = @deposit.cashouts.build
  end

    def create
    @deposit = current_user.deposit
    @cashout = @deposit.cashouts.build(cashout_params)
    @cashout.save 
    if @cashout.save
      flash[:success] = "Your order request has been sent!"
      redirect_to '/deposit'
    else
      flash[:error] = "Your order request hasn't been sent!"
      redirect_to '/deposit'
    end
  end

  def show
    @deposit = Deposit.find(params[:id])
    @deposit.cashout
  end


  private

    def cashout_params
      params.require(:cashout).permit(:order_sum)
    end

end

income.rb income.rb

class Income < ActiveRecord::Base
    belongs_to :deposit
    validates :deposit_id, :order_sum, presence: true
    validates :order_sum, numericality: true
    validates :order_sum, numericality: { greater_than_or_equal_to: 0}

    after_create :update_deposit_income

    private

    def update_deposit_income
        @deposit = self.deposit
        if @deposit.income == nil
            @income = 0
        else
            @income = @deposit.income
        end
        @deposit.update_attributes(:income => @income + self.order_sum)
    end
end

incomes_controller.rb incomes_controller.rb

class IncomesController < ApplicationController
  before_action :signed_in_user, only: [:create]

  def new
    @income = @deposit.incomes.build
  end

    def create
    @user = current_user
    @deposit = @user.deposit
    @income = @deposit.incomes.build(income_params) 
      @income.save
    if @income.save
      flash[:success] = "Your order request has been sent!"
      redirect_to '/deposit'
    else
      flash[:error] = "Your order request hasn't been sent!"
      redirect_to '/deposit' if current_user.present?
    end
  end

  def show
    @deposit = Deposit.find(params[:id])
    @deposit.income
  end


  private

    def income_params
      params.require(:income).permit(:order_sum)
    end

end

Where is my mistake? 我的错误在哪里?

The stack level too deep error usually happens because your code is stuck in a loop: either a method calling itself, or two methods calling each other repeatedly. stack level too deep错误通常是由于代码卡在一个循环中而发生的:一个方法调用自身,或者两个方法反复调用。

In your case i think it's caused by the validate_order method. 在您的情况下,我认为这是由validate_order方法引起的。 You are calling this in a before_save callback, and the method calls self.save , which will trigger the callback, which will call the method again, which will save again, which will trigger the callback etc etc. 您在before_save回调中调用此方法,该方法调用self.save ,将触发该回调,该回调将再次调用该方法,该方法将再次保存,将触发回调等。

Think about this for a moment - it doesn't make sense to save an object as part of it's "before_save" functionality does it? 暂时考虑一下-将对象保存为“ before_save”功能的一部分没有意义吗?

What i suspect you want to do is to just validate the object, and if validation fails that will automatically block the save anyway. 我怀疑您想做的只是验证对象,如果验证失败,无论如何将自动阻止保存。 Something like this 像这样

validate :validate_order

def validate_order
  @deposit = self.deposit
  @income = @deposit.income
  @cashout = self.order_sum
  if @income - @cashout <= 0
    self.errors.add(:deposit, "is too small")
  end
end

This is just an example as i don't know what the actual logic of what you are testing is supposed to be. 这只是一个示例,因为我不知道您要测试的内容的实际逻辑是什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM