我有一个名为PaymentNotifications
的模型。它仅用于记录付款,只要它们从Paypal有效。我需要检查他们给我的交易代码是否与我发布表单后从他们那里得到的交易代码相同。
所有这些都有效。我所做的是根据以下某些标准检查它是否有效:
在控制器中我有以下内容:
tx = params[:tx]
paypal_data = get_data_from_paypal(tx)
res_hash = create_hash(paypal_data)
@payment_notification = PaymentNotification.new(:params => res_hash, :quotation_id => res_hash['invoice'],:status => res_hash["payment_status"],:transaction_id => res_hash["txn_id"])
if paypal_data["SUCCESS"] && @payment_notification.is_valid?(tx) && @payment_notification.save
redirect_to thankyou_path(:id => @payment_notification.quotation_id)
else
render '/pages/error'
end
然后在模型中我运行我的方法is_valid?
validates :params, :quotation_id, :status, :transaction_id, presence: true
validates :transaction_id, :uniqueness => true
def is_valid?(tx)
amount_paid_valid?(params["payment_gross"]) && transaction_valid?(tx) && is_quotation_unpaid?
end
def transaction_valid?(tx)
if tx != transaction_id
errors.add(:transaction_id, "This transaction is not valid")
return false
else
return true
end
end
def is_quotation_unpaid?
if quotation.unpaid?
return true
else
errors.add(:quotation_paid, "This quotation has already been paid.")
return false
end
end
def amount_paid_valid?(amount_paid)
if amount_paid.to_i == quotation.price.to_i
return true
else
errors.add(:amount_paid, "The amount paid does not match the price quoted.")
return false
end
end
注意::amount_paid
和:quotation_paid
不是属性。它们只是错误消息的关键。
我想我在这里错过了这条船,因为必须有一种方法可以使用Rails中内置的验证来实现这一点,但我还不太擅长Rails。有人可以帮我重构一下,以便更容易维护并符合最佳实践吗?
答案 0 :(得分:1)
这里的主要问题是你重新实现了Rails已经拥有的东西 - 即一种检查AR对象是否有效的方法。如果您使用的是方法而不是内置的#valid?
,那么您的对象会继续传递#save
和#create
等操作,即使它们不应该这样做。
为了将您的自定义方法放入折叠并在调用内置验证时包含它们,只需在模型中将它们用作自定义验证,如下所示:
validates :params, :quotation_id, :status, :transaction_id, presence: true
validates :transaction_id, :uniqueness => true
validate :amount_paid_should_match_quote, :quotation_should_be_unpaid
validates_associated :transaction
private
def amount_paid_should_match_quote
if amount.to_i != quotation.price.to_i
errors.add(:amount, "does not match the price quoted")
end
end
def quotation_should_be_unpaid
if quotation.paid?
errors.add(:quotation, "has already been paid")
end
end
要注意的几个项目:
true
,这取决于Rails。validates_associated
即可。您可以在Rails Guides Validations documentation了解有关自定义验证的详情。