December 06, 2005

Ruby on Rails and validation

Ruby on Rails is radically changing the way developers look at Web applications, and it's great to see all the excitement that surrounds the many innovative features it offers.  One of these features is in-model validation, which is understandably seen as an improvement over validation tied to the presentation framework.

In this entry, Todd Huss shows a convincing example of this approach:

class Entry < ActiveRecord::Base

  # Relationships
  belongs_to :bliki

  # Validation
  validates_length_of :name, :within => 6..100
  validates_uniqueness_of :name
  validates_format_of :name, :with => /^\w+$/,
  :message => "cannot contain whitespace"
  validates_length_of :content, :minimum => 10
  validates_associated :bliki
end

This kind of code is fairly usual to any regular Ruby on Rails developer to the point where it's actually easy to overlook that there is something very wrong with it:  there is no easy way to capture this validation logic for reuse elsewhere.

I could move this validation to a common class but it's not good enough, for two reasons:

I still might want to fine tune a few parameters here and there (sometimes, the length of the name can be 6..100, other times 5..10 but the other constraints need to stay in place).

Not all my ActiveRecord objects extend the same class.

Has anyone tried to use a mix-in to achieve this?   Any other idea?

Posted by cedric at December 6, 2005 10:59 AM
Comments

One gripe I have with ActiveRecord is that the validation normally kicks in only when the entity is persisted or updated. This means your -- possibly invalid -- domain object goes through the web layer and your business logic until it gets caught by the validation framework.

I prefer the XWork/WebWork approach where the validation mechanisms can be context sensitive, and always apply immediately when the input data reaches the controller.

Posted by: Zsolt at December 6, 2005 12:18 PM

Cedric: It's actually quite easy to bundle all this up in either a mixin or your own meta validation. You could wrap it up into something like validates_cedricness_of :name and have that include both length, uniqueness, and format.

Zsolt: You can just call model.valid? to do this.

Posted by: David Heinemeier Hansson at December 6, 2005 12:52 PM

Zsolt,

You can manually invoke validation whenever you like by calling valid?

Posted by: Simon Harris at December 6, 2005 01:02 PM

Cool :)

Posted by: Zsolt at December 6, 2005 01:09 PM

Great, thanks David!

Posted by: Cedric at December 6, 2005 01:10 PM

For a system with a lot of GUIs, you really need to have a generic mechanism to transfer data back and forth anyway.

You really should define that mechanism with meta data. At least an XML template listing the objects/attributes rather than just throw a hashtable out there.

With those requirements identified, adding a simple drop-in validation into the XML definition should be pretty easy.

Just specify the name of the class used to validate the field and an optional string parameter. It certainly makes more sense than specifying the validation relationship in code anywhere.

This would allow you to specify much more than validations too, you could identify what to do with the data when it connects with any other sub-system.

Oh well, that's how I was designing it anyway.

Posted by: Bill Kress at December 6, 2005 05:37 PM

XML SUCKS!

Keep your horrid metadata away from rails!

Mixins can keep rails models much nicer, and keep the application simple.

Posted by: at December 6, 2005 05:42 PM

There's nothing wrong with the code if you don't want to reuse it though ;-) Thanks for the reference to my blog, nice to see folks are reading it. If I reach a point where I need to validate a name the same way in other parts of the code that would violate the DRY principle I like DHH's suggestion.

Posted by: Todd Huss at December 6, 2005 06:10 PM

Well, you don't just call valid() on an object to validate it, no, you ask the validation framework to validate the object:

ActionValidatorManager.validate(object, context);

But, as you do in Ruby, we could add this as a mixin using AOP to any objects we like to have the validation framework validate them.

One question for the Rails folks... How do you do context-sensitive validations? Also, how do you collect the validation error messages, and how do you localize them? These are all requirements that my validation framework (the XWork Validation Framework) had to address for real-world requirements at work.

Posted by: Jason Carreira at December 7, 2005 11:42 AM

I really like the Mixin idea. You can then break out all your common validation rules into a set of declarative classes, and mixin as needed. Kind of like meta-data validation rules, but its not metadata. Nice.

Three cheers for mixins.

Posted by: Michael Neale at December 8, 2005 02:58 PM

What you need to do is Mixin with AOP then Inject with IoC, squeeze in a Context, implement IValidatable and finally let it sit overnite.

wallah !!!

Posted by: Jesus at December 8, 2005 03:31 PM

We have not had a need to do context-sensitive validations and I'd argue that most applications do not. So the the validation rules that you specify in the Rails models are the absolutes, the "must always be true" kind of validations.

If you have context-sensitive validations needed on top of that, you'll have to roll on your own. So this is one of those "most people, most of the time" things. We're not after the "all people, all of the time" kind of framework coverage.

Posted by: David Heinemeier Hansson at December 9, 2005 12:22 PM

[quote]
We have not had a need to do context-sensitive validations and I'd argue that most applications do not. So the the validation rules that you specify in the Rails models are the absolutes, the "must always be true" kind of validations.

If you have context-sensitive validations needed on top of that, you'll have to roll on your own. So this is one of those "most people, most of the time" things. We're not after the "all people, all of the time" kind of framework coverage.
[/quote]

hmm, well look at the first post in this thread. There is a real use case for the need of it. What I like in XWork/WW approach (same goes for Spring with its rules validations) even more is that I can run the same validation in multiple layers presentation and business, and if my business and presentation sit on the same JVM I can propagate validation that was done already into the business layer so it does not waste its time re-checking. He, he no need for context sensitive validation --> you must be kidding me.

Posted by: Alex Shneyderman at December 19, 2005 11:48 AM

[quote]
We have not had a need to do context-sensitive validations and I'd argue that most applications do not. So the the validation rules that you specify in the Rails models are the absolutes, the "must always be true" kind of validations.

If you have context-sensitive validations needed on top of that, you'll have to roll on your own. So this is one of those "most people, most of the time" things. We're not after the "all people, all of the time" kind of framework coverage.
[/quote]

hmm, well look at the first post in this thread. There is a real use case for the need of it. What I like in XWork/WW approach (same goes for Spring with its rules validations) even more is that I can run the same validation in multiple layers presentation and business, and if my business and presentation sit on the same JVM I can propagate validation that was done already into the business layer so it does not waste its time re-checking. He, he no need for context sensitive validation --> you must be kidding me.

Posted by: Alex Shneyderman at December 19, 2005 11:49 AM

Ref: Contextual validation use cases
I think this is mis-named to be honest (and getting lots of google hits for the wrong thing). I would call this multi-layer validation and the great thing about RoR is the fact that it isn't clunky like Spring and other Java frameworks I have worked with (I have had 8-9 years of professional Java experience and 2 year of Python and Ruby, so I am not just a Ruby head or anti-Java head).

In fact, even Marc Fluery of JBoss (a big Java head) agrees that keeping your apps as thin and stateless as possible is best for scaling apps to handle significant load. You may or may not like his arrogant way, but I think in this instance he makes a genuinely great point. Why uber-architects insist on having multiple seperate containers for their apps unless extremely domain-specific use cases mandate this is beyond me.

I have worked with plenty of uber-architects that want to redesign the world to make it even more generic than the vast majority of real world use cases need them to be and ALL of those projects have been complete failures. Of course, the opposite extreme also produces project failures. However, if we agree that RoR's main focus is on helping application developers build streamlined web applications and that Marc Fluery has a good point, then I would argue that this is a moot point.

But if you like Spring so much, stick to it, please!

As for those that are interested in doing what I would call context-sensitive validation...

RoR provides the validate, validate_on_create and validate_on_update protected methods for application developers to override them. This seems like the perfect place to do contextual validation.

Posted by: S. Potter at April 23, 2006 03:21 PM

how to perform email validation i m confused when i m using following coe it return code it not consider index('') method of ruby in model.

mymodwl.rb

def validate
apos=:email.index('@').to_i
dotpos=:email.rindex(".")
lastpos=:email.length-1;
if (apos 3 || lastpos-dotpos<2)
errors.add(:email, "is missing or invalid")
end
end

Posted by: vipul at July 26, 2006 07:21 AM

apos=:email.index(/@/).to_i

use this code

Posted by: lurker at December 25, 2006 12:29 AM

i have make upload image form, i save path info about image on database and i placed uploaded image to public/images/user_pix/ directory

everything is running well, except i can't validate content type of image, my apps accept jpg,gif & png filetype only

so guys, would you please tell me how to validate content type when you save/update image data

*i'm sorry if my english bad

Posted by: Aditya Agustyana at February 13, 2007 09:23 PM

hkh

Posted by: at March 9, 2007 04:20 AM

In my address model, I have address line 1 and address line 2. Address line 2 is optional and I want to validate it when present. So, I defined the following validate function.

def validate
if(!address_line_2.nil? and !address_line_2.blank?)
validates_length_of :address_line_2, :maximum => 30, :too_long => " exceeds %d characters"
validates_format_of :address_line_2, :with => /^(\w+|(\s|,|-|\.|')*)+$/
return true
end
end

But rails throws a NoMethodFound exception for validates_length_of. How can I fix it?

Posted by: bijah at November 25, 2007 03:26 PM

OK. I solved it as follows:

validates_length_of :address_line_2, :maximum => 30, :too_long => " exceeds %d characters", :if => Proc.new { |a| !a.addres
s_line_2.blank? }
validates_format_of :address_line_2, :with => /^(\w+|(\s|,|-|\.|')*)+$/, :if => Proc.new { |a| !a.address_line_2.blank? }

But I still would like to know the cause for the NoMethodFound error in the previous approach.

Thanks.

Posted by: bijah at November 25, 2007 07:53 PM

ds

Posted by: sdf at April 23, 2008 06:21 AM

Lav ban eq asum

Posted by: Gevorik u Goqor at April 23, 2008 06:22 AM

hello

Posted by: aditi at May 22, 2008 10:21 PM

ruby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input ruruby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input ruby rails input validation example codevalidatiruby rails input validation example codeon exampruby rails input validation example codele coderruby rails input validation example codeuby railruby rails input validation example codes input ruby rails input validation example codevalidatiruby rails input validation example codeon exampruby rails input validation example codele codebruby ruby rails input validation example coderuby rails input validation example coderuby rails ruby rails input validation example codeinput validation example coderuby rails input validation example coderuby rails input validation example coderails input validation example codey rails ruby rails input validation example codeinput ruby rails input validation example codevalidation example codevalidation example coderuby raruby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example codeils input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example coderuby rails input validation example code

Posted by: at October 14, 2008 11:48 AM
Post a comment






Remember personal info?