Forum: Ruby on Rails Multiple Model Validation

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dylan S. (Guest)
on 2006-01-27 21:19
(Received via mailing list)
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 :)
Bob S. (Guest)
on 2006-01-27 21:31
(Received via mailing list)
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: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:19 AM
To: removed_email_address@domain.invalid
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 :)
Dylan S. (Guest)
on 2006-01-27 21:37
(Received via mailing list)
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 :)
Tom M. (Guest)
on 2006-01-27 22:08
(Received via mailing list)
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?
Duane J. (Guest)
on 2006-01-27 22:14
(Received via mailing list)
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 :)
>

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/
Bob S. (Guest)
on 2006-01-27 22:17
(Received via mailing list)
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: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:35 AM
To: removed_email_address@domain.invalid
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 :)




On 1/27/06, Bob S. <removed_email_address@domain.invalid> 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: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Dylan S.
Sent: Friday, January 27, 2006 11:19 AM
To: removed_email_address@domain.invalid
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 :)
Bob S. (Guest)
on 2006-01-27 22:17
(Received via mailing list)
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: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Tom M.
Sent: Friday, January 27, 2006 12:04 PM
To: removed_email_address@domain.invalid
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.
Dylan S. (Guest)
on 2006-01-27 22:47
(Received via mailing list)
Awesome.  Thank you guys very much.  This more than solves my problems
:)
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 !
Dylan S. (Guest)
on 2006-01-27 23:44
(Received via mailing list)
Duane... forgive my ignorance... where do I put your modified
active_record_helper.rb file ?
I've obviously never overridden any of rails before :)
Pat M. (Guest)
on 2006-01-27 23:54
(Received via mailing list)
You can throw it in lib/
Dylan S. (Guest)
on 2006-01-28 00:24
(Received via mailing list)
Thanks Pat.  I'm unsuccessfully trying this :)  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  :))
Pat M. (Guest)
on 2006-01-28 00:39
(Received via mailing list)
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
Dylan S. (Guest)
on 2006-01-28 01:09
(Received via mailing list)
I'm actually here at the Rails Studio in Pasadena, and have the experts
looking into it ;)
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 :)  Thanks Pat !
Duane J. (Guest)
on 2006-01-28 01:57
(Received via mailing list)
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 ;)
> 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 :)  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/
Dylan S. (Guest)
on 2006-01-28 03:07
(Received via mailing list)
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 :)

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 !
Dylan S. (Guest)
on 2006-01-28 03:13
(Received via mailing list)
Actually... Duane, how are you implementing this code ?  Are you putting
this in lib/ ?  If you are, what is the file name ?
Duane J. (Guest)
on 2006-01-28 03:34
(Received via mailing list)
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/
Dylan S. (Guest)
on 2006-01-28 18:39
(Received via mailing list)
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 !"  :)
This topic is locked and can not be replied to.