I ran into an issue today where I wanted to skip validations based on where an object was created. To be more specific, I wanted to validate strictly if a “venue” was created through my web interface but I want to skip validations when importing venues. The reasoning is pretty simple, I want to require that a user provides a zip code, state, etc. if they use my web interface. However, if I import venues from a website with CRON at some frequency, I want to gather as much venue data as possible and ask users to update it later if needed.
This is not very straightforward in Rails. After all, I do not want to skip validations entirely. I ended up creating a virtual attribute for validations I wanted to skip and checking the attribute before validating:
validates_presence_of :name validates_presence_of :country_id, :unless => "!validations_to_skip.nil? and validations_to_skip.include?('country')" validates_presence_of :region_id, :unless => "!validations_to_skip.nil? and validations_to_skip.include?('region')" validates_presence_of :city, :unless => "!validations_to_skip.nil? and validations_to_skip.include?('city')" validates_presence_of :zip, :unless => "!validations_to_skip.nil? and validations_to_skip.include?('zip')" validates_existence_of :user # array of validations to skip attr_accessor :validations_to_skip attr_protected :validations_to_skip
You can put something like that at the top of your model file. Be sure to protect the virtual attribute so an attacker cannot set validations_to_skip from a web request in cases where you mass assign the model attributes.
To skip validations just do something like this when you create a venue:
v = Venue.new v.validations_to_skip = ["country","region","city","zip"] v.name = "A Venue" v.user = some_user v.save
What do you think? Anyone have a better way?
If you enjoyed this post, make sure you subscribe to my RSS feed!











4 Comments
That’s pretty nice, I’ve also had a need to do something similar in the past. It would be nice to make a plugin for this which DRYed up the syntax a bit, so you could just mark a validation as skippable:
Maybe a project for Open Source Hack Night?
@paul I agree we could DRY this up with a plugin. How would AR know to check if it should skip a validation? Saying a validation is “skippable” is not enough, we need to be able to set a flag in our code as well so we know when to skip the validation. From a security standpoint, I definitely agree that we should have to white list the attributes that are even possible to skip which is where your code above makes great sense.
I think defining which validations are skippable per object, similar to what you have, makes sense. The plugin could take care of defining that accessor.
awesome, exactly what I was looking for
cheers