che*_*ell 29 callback ruby-on-rails-4
如果有孩子,我试图阻止记录被销毁.
class Submission < ActiveRecord::Base
has_many :quotations, :dependent => :destroy
before_destroy :check_for_payments
def quoted?
quotations.any?
end
def has_payments?
true if quotations.detect {|q| q.payment}
end
private
def check_for_payments
if quoted? && has_payments?
errors[:base] << "cannot delete submission that has already been paid"
false
end
end
end
class Quotation < ActiveRecord::Base
#associations
belongs_to :submission
has_one :payment_notification
has_one :payment
before_destroy :check_for_payments
private
def check_for_payments
if payment_notification || payment
errors[:base] << "cannot delete quotation while payment exist"
return false
end
end
end
Run Code Online (Sandbox Code Playgroud)
当我测试此代码时,before_destroy:check_for_payments会阻止删除Quotation记录.
但是:提交before_destroy回调中的:check_for_payments不会停止提交被删除.
如何通过销毁付款来停止提交?
And*_*res 48
在Rails 5中,throw :abort否则它将无法工作.(甚至返回false)
这样的事情应该有效:
class Something < ApplicationRecord
before_destroy :can_destroy?
private
def can_destroy?
if model.something?
errors[:base] << "Can't be destroy because of something"
throw :abort
end
end
Run Code Online (Sandbox Code Playgroud)
gri*_*ocl 30
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html 订购回调(我改变了这个具体例子的措辞)
有时代码需要回调以特定顺序执行.例如,在引用被+ dependent:destroy +选项销毁之前,应该执行before_destroy回调(在这种情况下为check_for_payments).
在这种情况下,问题是当执行before_destroy回调时,引用不可用,因为首先执行destroy回调.您可以在before_destroy回调上使用prepend选项来避免这种情况.
before_destroy :check_for_payments, prepend: true
Run Code Online (Sandbox Code Playgroud)
我用上面描述的相同模型制作了一个新应用程序,然后进行了提交测试.它非常难看,我只是在学习......
class Submission < ActiveRecord::Base
has_many :quotations, :dependent => :destroy
before_destroy :check_for_payments, prepend: true
def quoted?
quotations.any?
end
def has_payments?
true if quotations.detect {|q| q.payment }
end
private
def check_for_payments
if quoted? && has_payments?
errors[:base] << "error message"
false
end
end
end
class Quotation < ActiveRecord::Base
belongs_to :submission
has_one :payment_notification
has_one :payment
before_destroy :check_for_payments
private
def check_for_payments
if payment_notification || payment
errors[:base] << "cannot delete quotation while payment exist"
return false
end
end
end
require 'test_helper'
class SubmissionTest < ActiveSupport::TestCase
test "can't destroy" do
sub = Submission.new
sub.save
quote = Quotation.new
quote.submission_id = sub.id
quote.save
pay = Payment.new
pay.quotation_id = quote.id
pay.save
refute sub.destroy, "destroyed record"
end
end
Run Code Online (Sandbox Code Playgroud)
它过去了!我希望有所帮助.
And*_*ing 26
我会尝试下面的代码:
any?没有块的情况下使用导致使用关联计数器缓存(如果已定义)或者如果已经加载了关联的大小并且如果需要则失败SQL COUNT来避免不必要的记录检索报价和支付.q.payment关联代理的真实性/存在,这对has_xxx不起作用.如果您想测试在线使用情况q.payment.present?尝试以下操作,看看你如何去:
class Submission < ActiveRecord::Base
has_many :quotations,
inverse_of: :submission,
dependent: :destroy
has_many :payments,
through: :quotations
before_destroy :check_for_payments, prepend: true
private
def check_for_payments
if payments.any?
errors[:base] << "cannot delete submission that has already been paid"
return false
end
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27072 次 |
| 最近记录: |