在 Rails 中向模型添加错误不起作用
Posted
技术标签:
【中文标题】在 Rails 中向模型添加错误不起作用【英文标题】:adding errors to model in rails is not working 【发布时间】:2013-05-19 03:21:09 【问题描述】:好吧,这没有意义。我可以向模型添加错误,但是当我调用有效时?或保存!它删除了我添加的错误。但是,常规验证将阻止模型被保存。为什么 errors.add 不起作用?
1.9.3p0 :001 > @order = Order.new(email: 'some@email.com')
=> #<Order id: nil, name: nil, address: nil, email: "some@email.com", pay_type: nil, created_at: nil, updated_at: nil, paypal_customer_token: nil, paypal_recurring_profile_token: nil, first_name: nil, last_name: nil, account_details: , unit_id_for_plan: nil, invoice: nil, purchased_at: nil>
1.9.3p0 :002 > @order.valid?
=> true
1.9.3p0 :003 > @order.errors.add :base, 'error'
=> ["error"]
1.9.3p0 :004 > @order.errors.size
=> 1
1.9.3p0 :005 > @order.valid?
=> true
1.9.3p0 :006 > @order.errors.size
=> 0
1.9.3p0 :007 > @order.errors.add :base, 'error_again'
=> ["error_again"]
1.9.3p0 :008 > @order.errors.size
=> 1
1.9.3p0 :009 > @order.save!
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO `orders` (`account_details`, `address`, `created_at`, `email`, `first_name`, `invoice`, `last_name`, `name`, `pay_type`, `paypal_customer_token`, `paypal_recurring_profile_token`, `purchased_at`, `unit_id_for_plan`, `updated_at`) VALUES ('--- \n', NULL, '2013-05-23 18:17:18', 'some@email.com', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2013-05-23 18:17:18')
(12.6ms) COMMIT
=> true
1.9.3p0 :010 > @order.errors.size
=> 0
Order 模型不包含太多验证:
attr_accessible :address, :email, :name, :pay_type, :paypal_customer_token, :paypal_payment_token, :first_name, :last_name, :account_details, :invoice
has_one :cart
has_many :line_items, :through => :cart
has_many :products, :through => :line_items, :source => :sellable, :source_type => 'Product'
has_many :airtime_plans, :through => :line_items, :source => :sellable, :source_type => 'AirtimePlan'
has_many :payment_notifications
serialize :account_details, Hash
validates_presence_of :email
validates_presence_of :email 正确会阻止保存工作,但是当我使用 errors.add :base 时,它不起作用。
@LeoCorrea 的回答让我想出了这个解决方案:
validate :user_validation, :on => :create
attr_accessor :users_invalid
def user_validation
if users_invalid
errors[:base] << "You have invalid user records"
end
end
#paypal_payment model in which the order is passed into
elsif resp["status"] == "error"
#@order.errors.add(:base, resp["body"])
@order.users_invalid = true
end
问题是我想要的实际错误消息在 resp["body"] 中。现在我刚刚添加了一条无用的消息“您的用户记录无效”。
【问题讨论】:
我认为我们需要您的完整save_with_payment
方法
@user1737909 我添加了完整的方法
还有你的验证器......不过我注意到一件事,在你的方法中,你使用的是save!
,它会在错误时引发异常,而不是save
,它返回真/假。但我认为这是次要的,我会先检查您的验证。
@dpassage 我更新了问题。这甚至在控制台中都不起作用。
我认为您需要在验证阶段添加错误。事后为时已晚。
【参考方案1】:
AR 模型上的valid?
会清除错误数组,它不会检查错误数组中是否有错误。至于save!
,它运行与错误数组无关的验证。如果您想在模型中出现错误,则需要向其添加验证。
如果您阅读valid?
的代码,您将看到以下内容
ActiveRecord::Validations
def valid?(context = nil)
context ||= (new_record? ? :create : :update)
output = super(context)
errors.empty? && output
end
super(context)
的调用只是对 ActiveModel::Validations#valid?
的调用,它负责在运行验证之前清除错误数组:
ActiveModel::Validations
def valid?(context = nil)
current_context, self.validation_context = validation_context, context
errors.clear
run_validations!
ensure
self.validation_context = current_context
end
更新
为了添加您的自定义错误,您必须在验证方法上执行此操作,该验证方法会在检查验证时添加它。当您重新运行验证时,之前或之后的任何内容都将被清除。
看看这个资源http://guides.rubyonrails.org/active_record_validations.html#errors
错误被添加到通过验证调用的方法中。
【讨论】:
好的,因为我必须在完全不同的模型中添加错误,这意味着我必须创建一个 attr_accessor 并将其设置为 true。然后创建自定义验证并检查 attr_accessor 是否设置为 true,如果为 true,则添加到 errors[:base]。但这仍然引发了一个问题,到那时,我不知道实际的错误消息是什么。 我不关注你...在什么情况下你必须添加另一个模型的错误?这只会使这两个模型紧密耦合。 您需要做什么或者在什么情况下需要添加错误?更新你的答案来回答这个问题。 paypal_payment 模型不是 Rails 模型。它用于支付宝功能,但没有数据库或任何东西。 我想我的问题是,如果您只是要重新验证它或稍后尝试保存它,那么将错误添加到 @orders 实例有什么用?如果来自贝宝的响应无效,您应该将该信息转发给用户吗?我知道你想要做什么我只是没有看到你的整个实现,所以我不能对此发表太多评论。以上是关于在 Rails 中向模型添加错误不起作用的主要内容,如果未能解决你的问题,请参考以下文章
反应:通过状态钩子在 loginHandler 函数中向 localStorage 添加令牌不起作用
在 ng-repeat 中向 ng-click 函数添加参数似乎不起作用
带有has_many的模型中的属性总和:通过关联在Rails 5中不起作用