[英]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.