Multiple Model Validation

Hey All !

I have a form which contains two models. I would like both models to be
validated, but have their validations aggregated on the page.

If I do:
<%= error_messages_for(:model1) %>
<%= error_messages_for(:model2) %>

It puts two big validation blocks on the page. I would like all the
errors
from both models, but only in one validation box.
Is this possible ? All my attempts have failed thus far :slight_smile:

Hi Dylan,

This is something I was planning on adding to my Enhances Rails Errors
plugin, maybe I can take a quick look and see what it would take.

Iā€™ll get back to you in an hour or two. I can make error_messages_for
take a
hash of objects, but the problem is dealing with duplicate column_names
and
the default header text displayed.

Handling the default header can be accomplished by using the :header
option
in the plugin. Duplicate column names is a bit more complex.

For now, I will forego duplicate name handling until I can engineer an
easy
solution that works with the other functionality of the plugin

Bob S.

http://www.railtie.net/


From: [email protected]
[mailto:[email protected]] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:19 AM
To: [email protected]
Subject: [Rails] Multiple Model Validation

Hey All !

I have a form which contains two models. I would like both models to be
validated, but have their validations aggregated on the page.

If I do:
<%= error_messages_for(:model1) %>
<%= error_messages_for(:model2) %>

It puts two big validation blocks on the page. I would like all the
errors
from both models, but only in one validation box.
Is this possible ? All my attempts have failed thus far :slight_smile:

Ahhā€¦ excellent, thanks Bob !

This seems like a ticketable itemā€¦ and, I would have to say your
validates_numericality_of extensions should be too. +1 vote for you
throwing that in as an enhancement request :slight_smile:

On Jan 27, 2006, at 11:31 AM, Bob S. wrote:

IĆ¢??ll get back to you in an hour or two. I can make
error_messages_for take a hash of objects, but the problem is
dealing with duplicate column_names and the default header text
displayed.
Hello Bob.

Iā€™ve seen you mention your revised error_messages_for as taking a
hash of objects, but wouldnā€™t an array suffice?

On Jan 27, 2006, at 12:19 PM, Dylan S. wrote:

the errors from both models, but only in one validation box.
Is this possible ? All my attempts have failed thus far :slight_smile:

I almost always override the default error_message_for method for
my apps. Hereā€™s what I use:

Overrides the implementation of ActionView:Helpers:ActiveRecordHelper

Returns a string with a div containing all the error messages for

the object

located as an instance variable by the name of object_name. This

div can be

tailored by the following options:

* header_tag - Used for the header of the error div (default: h2)

* id - The id of the error div (default: errorExplanation)

* class - The class of the error div (default: errorExplanation)

module ActionView::Helpers::ActiveRecordHelper
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_eval ā€œ@#{object_name}ā€
unless object.errors.empty?
content_tag(ā€œdivā€,
content_tag(options[:header_tag] || ā€œh2ā€, ā€œPlease correct
the following:ā€) +
content_tag(ā€œulā€, object.errors.full_messages.collect { |
msg| content_tag(ā€œliā€, msg) }),
ā€œidā€ => options[:id] || ā€œerrorExplanationā€, ā€œclassā€ =>
options[:class] || ā€œerrorExplanationā€
)
end
end #def error_messages_for
end #class ActionView::Helpers::ActiveRecordHelper

It shouldnā€™t be too difficult to just add your own loop in there to
handle multiple objects if thatā€™s needed.

Duane J.
(canadaduane)
http://blog.inquirylabs.com/

Yea, I typed the wrong thing. Didnā€™t want to waste another spot in
everyones
inbox to correct myself. Good eye though.

Bob S.

http://www.railtie.net/


From: [email protected]
[mailto:[email protected]] On Behalf Of Tom M.
Sent: Friday, January 27, 2006 12:04 PM
To: [email protected]
Subject: Re: [Rails] Multiple Model Validation

On Jan 27, 2006, at 11:31 AM, Bob S. wrote:

Iā€™ll get back to you in an hour or two. I can make error_messages_for
take a
hash of objects, but the problem is dealing with duplicate column_names
and
the default header text displayed.

Hello Bob.

Iā€™ve seen you mention your revised error_messages_for as taking a hash
of
objects, but wouldnā€™t an array suffice?

ā€“

ā€“ Tom M.

Hi Dylan,

You can download version 0.2 now. Now you can pass in an array of
object_names and have them consolidated in one error container.

As I said before, it doesnā€™t properly handle duplicate column names,
last
column defined wins. All the other enhancements will continue to work
though, so you can intermix the order of the errors between the objects
to
match your form layout.

You will probably want to override the :header as it substitutes the
first
object_name passed in when referring to the object it has errors for.

Let me know how it works for you.

<%= error_messages_for [ā€˜object_1ā€™, ā€˜object_2ā€™], :header => ā€˜Whoops,
please
fix these errors and try again.ā€™ %>

http://www.railtie.net/plugins/error_messages_for-0.2.zip

Cheers,

Bob S.

http://www.railtie.net/


From: [email protected]
[mailto:[email protected]] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:35 AM
To: [email protected]
Subject: Re: [Rails] Multiple Model Validation

Ahhā€¦ excellent, thanks Bob !

This seems like a ticketable itemā€¦ and, I would have to say your
validates_numericality_of extensions should be too. +1 vote for you
throwing that in as an enhancement request :slight_smile:

On 1/27/06, Bob S. [email protected] wrote:

Hi Dylan,

This is something I was planning on adding to my Enhances Rails Errors
plugin, maybe I can take a quick look and see what it would take.

Iā€™ll get back to you in an hour or two. I can make error_messages_for
take a
hash of objects, but the problem is dealing with duplicate column_names
and
the default header text displayed.

Handling the default header can be accomplished by using the :header
option
in the plugin. Duplicate column names is a bit more complex.

For now, I will forego duplicate name handling until I can engineer an
easy
solution that works with the other functionality of the plugin

Bob S.

http://www.railtie.net/


From: [email protected]
[mailto:[email protected]] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:19 AM
To: [email protected]
Subject: [Rails] Multiple Model Validation

Hey All !

I have a form which contains two models. I would like both models to be
validated, but have their validations aggregated on the page.

If I do:
<%= error_messages_for(:model1) %>
<%= error_messages_for(:model2) %>

It puts two big validation blocks on the page. I would like all the
errors
from both models, but only in one validation box.
Is this possible ? All my attempts have failed thus far :slight_smile:

Awesome. Thank you guys very much. This more than solves my problems
:slight_smile:
Iā€™ll probably play around with both of your suggestions, and Bob, Iā€™ll
let
you know if I run into any quirks.
Thanks again !

You can throw it in lib/

Duaneā€¦ forgive my ignoranceā€¦ where do I put your modified
active_record_helper.rb file ?
Iā€™ve obviously never overridden any of rails before :slight_smile:

Assuming you copied Duaneā€™s code completely then it ought to simply go
in lib/, because the ā€˜module ActionView::Helpers::ActiveRecordHelperā€™
take care of the namespace stuff. But I guess itā€™s obvious that itā€™s
not working, so Iā€™m wrong on this one.

Pat

Thanks Pat. Iā€™m unsuccessfully trying this :slight_smile: Is there a good doc on
how
to do these overrides ?

Iā€™ve tried both:
/lib/active_record_helper.rb
/lib/action_view/helpers/active_record_helper.rb

No dice. (opening pickaxe now :))

Iā€™m actually here at the Rails Studio in Pasadena, and have the experts
looking into it :wink:
I put the code into environment.rb, and it works fine. So, something
fishy
with the loading Iā€™d assume.
Hmmmā€¦ Iā€™ll let you know what we find out :slight_smile: Thanks Pat !

On Jan 27, 2006, at 4:07 PM, Dylan S. wrote:

Iā€™m actually here at the Rails Studio in Pasadena, and have the
experts looking into it :wink:
I put the code into environment.rb, and it works fine. So,
something fishy with the loading Iā€™d assume.
Hmmmā€¦ Iā€™ll let you know what we find out :slight_smile: Thanks Pat !

As far as I know, files in lib/ are automatically loaded only when
there is a class or module by the same name as the class. For
example, if you created

class Extension
end

and put it in lib/extension.rb, then it would be autoloaded by the
Rails dependency code.

However, since this isnā€™t the case here, the file needs to be
included from environment.rb:

require_dependency 'custom_error_messages'

and then, of course, youā€™d put the code I posted up earlier inside of
lib/custom_error_messages.rb.

Hope that works for you!

Duane J.
(canadaduane)
http://blog.inquirylabs.com/

Actuallyā€¦ Duane, how are you implementing this code ? Are you putting
this in lib/ ? If you are, what is the file name ?

Ahhā€¦ interesting.
All my different tests have failed, and Iā€™m assuming your
ā€˜require_dependencyā€™ approach is the only one that will work.
It would be really nice to be able to simply throw that code into lib/
and
have it workā€¦ however, thatā€™s not the case :slight_smile:

Iā€™m about to hit up Dave about it to see what his opinion is. Might as
well
hit up the source while I can !
Thanks Duane !

On Jan 27, 2006, at 6:12 PM, Dylan S. wrote:

Actuallyā€¦ Duane, how are you implementing this code ? Are you
putting this in lib/ ? If you are, what is the file name ?

In environment.rb:

require ā€˜custom_error_messages_forā€™

in lib/custom_error_messages_for.rb:

Overrides the implementation of ActionView:Helpers:ActiveRecordHelper

Returns a string with a div containing all the error messages for

the object

located as an instance variable by the name of object_name. This

div can be

tailored by the following options:

* header_tag - Used for the header of the error div (default: h2)

* id - The id of the error div (default: errorExplanation)

* class - The class of the error div (default: errorExplanation)

module ActionView::Helpers::ActiveRecordHelper
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_eval ā€œ@#{object_name}ā€
unless object.errors.empty?
content_tag(ā€œdivā€,
content_tag(options[:header_tag] || ā€œh2ā€, ā€œPlease correct
the following:ā€) +
content_tag(ā€œulā€, object.errors.full_messages.collect { |
msg| content_tag(ā€œliā€, msg) }),
ā€œidā€ => options[:id] || ā€œerrorExplanationā€, ā€œclassā€ =>
options[:class] || ā€œerrorExplanationā€
)
end
end #def error_messages_for
end #class ActionView::Helpers::ActiveRecordHelper

Duane J.
(canadaduane)
http://blog.inquirylabs.com/

Excellent, thanks Duane. I was assuming Iā€™d have to override the
method,
but creating a new one is just as good in this case.
It works like a charm ! Thanks again !

psā€¦ Mike and Dave say ā€œHi !ā€ :slight_smile: