Ok this is not making sense. I can add an error to the model, but when I call valid? or save! it deletes the error that I added. However, the regular validations will prevent model from being saved. Why isn't errors.add working?
1.9.3p0 :001 > @order = Order.new(email: '[email protected]')
=> #<Order id: nil, name: nil, address: nil, email: "[email protected]", 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', '[email protected]', 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
The Order model doesn't contain much validation:
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
The validates_presence_of :email correctly will prevent save from working, but when I use errors.add :base, it doesn't work.
@LeoCorrea answer led me to come up with this solution:
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
The problem is the actual error message I want is in resp["body"]. Right now I just added an unhelpful message "You have invalid user records".
valid?
on a AR model clears the errors array, it does not check for whether you have errors in the errors array or not. As for save!
it runs validations which have nothing to do with the errors array. If you want to have errors in your model, you need to add validations to it.
If you read the code for valid?
this is what you'll see
ActiveRecord::Validations
def valid?(context = nil)
context ||= (new_record? ? :create : :update)
output = super(context)
errors.empty? && output
end
The call of super(context)
is just a call to ActiveModel::Validations#valid?
which is the one responsible for clearing the errors array before running validations:
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
UPDATE
In order to add your custom errors, you have to do it on a validation method which adds it when the validation is checked. Anything before or after will just be cleared when you re-run validations.
Take a look at this resource http://guides.rubyonrails.org/active_record_validations.html#errors
The errors are added on a method that is called with validation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With