Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.2 Prevent Object from being Saved using Errors

I have an ActiveRecord object and I would like to prevent it from being saved, without having permanent validations on the model. You used to be able to do something like this using errors.add but it doesn't look like it works anymore.

user = User.last
user.errors.add :name, "name doesn't rhyme with orange"
user.valid? # => true
user.save   # => true

or

user = User.last
user.errors.add :base, "my unique error"
user.valid? # => true
user.save   # => true

How can I prevent the user object from getting saved in Rails 3.2 without modifying it's model?

like image 745
Schneems Avatar asked Mar 12 '12 20:03

Schneems


3 Answers

You can set errors, but do it within a validate method, e.g.:

validate :must_rhyme_with_orange

def must_rhyme_with_orange
  unless rhymes_with_orange?
    errors.add(:name, "doesn't rhyme with orange")
  end
end

If you want to conditionally run the validation, one trick is to use attr_accessor and a guard condition:

attr_accessor :needs_rhyming

validate :must_rhyme_with_orange, :if => Proc.new {|o| o.needs_rhyming}

> u = User.last
> u.needs_rhyming = true
> u.valid? # false
like image 94
zetetic Avatar answered Nov 07 '22 13:11

zetetic


Your issue is running valid? will rerun the validations.. resetting your errors.

     pry(main)> u.errors[:base] << "This is some custom error message"
     => ["This is some custom error message"]
     pry(main)> u.errors
     => {:base=>["This is some custom error message"]}
     pry(main)> u.valid?
     => true
     pry(main)> u.errors
     => {}
     pry(main)> 

Instead, just check if u.errors.blank?

like image 24
Ben Miller Avatar answered Nov 07 '22 11:11

Ben Miller


This is a slight deviation from the original question, but I found this post after trying a few things. Rails has built in functionality to reject an object from saving if it has the _destroy attribute assigned as true. Quite helpful if you're handling model creation on the controller level.

like image 1
Kevin Hsieh Avatar answered Nov 07 '22 13:11

Kevin Hsieh