# Handling validation failures on hasmany through records

**URL:** <https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050>\
**Category:** Rails\
**Created:** [March 16, 2007, 7:19pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050 "2007-03-16T19:19:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 16, 2007, 7:19pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/1 "2007-03-16T19:19:08Z")

</div>

Hi all,

I am fairly new to Ruby and RoR but am making pretty good progress. But  
this has me stumped and I wonder if anyone can point me in the right  
direction. I haven’t been able to find any examples on the web that  
shine the light on this yet.

I have a very simple hasmany :through model as follows:

class Member \< ActiveRecord::Base  
has\_many :member\_phones, :dependent =\> :destroy  
has\_many :phones, :through =\> :member\_phones  
validates\_exclusion\_of :first\_name, :in =\> [“Bozo”], :message =\> “You  
don’t belong here”  
end

class MemberPhone \< ActiveRecord::Base  
belongs\_to :member  
belongs\_to :phone  
validates\_exclusion\_of :name, :in =\> [“Foobar”], :message =\> “No  
Foobar Allowed”  
end

class Phone \< ActiveRecord::Base  
has\_many :member\_phones  
has\_many :people, :through =\> :member\_phones  
end

And this all works fine. The application can do all the CRUD functions,  
and the validations really fail when they should.

My problem is that if I enter a phone named Foobar, it will fail to add  
the record just as it should, but it does so silently. I cannot figure  
out how to display an error message for it.

I can use \<%= error\_messages\_for ‘member’ %\> to display the error  
message if I add a member with a first name of Bozo, but I can’t figure  
out how to get hold of the error message for the phone.

Does anyone know how to get and display the error messages on these  
associated tables?

–Will

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 16, 2007, 7:32pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/2 "2007-03-16T19:32:11Z")

</div>

Hi, I noticed that within your Phone model is referencing :people.  
Thus, the Phone model should be

class Phone \< ActiveRecord::Base  
has\_many :member\_phones  
has\_many :members, :through =\> :member\_phones  
end

Good luck,

-Conrad

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 16, 2007, 9:03pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/3 "2007-03-16T21:03:22Z")

</div>

Conrad T. wrote:

> Hi, I noticed that within your Phone model is referencing :people.  
> Thus, the Phone model should be
> 
> class Phone \< ActiveRecord::Base  
> has\_many :member\_phones  
> has\_many :members, :through =\> :member\_phones  
> end

Thanks Conrad, your right, that was a typo and I have corrected it.  
However, it does not appear to be the cause of my trouble. The fixed  
version still fails silently.

I am tying to take on each area of RoR in turn. Right now I’m trying to  
figure out validations. ;^)

thanks all,  
–Will

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 17, 2007, 11:24pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/4 "2007-03-17T23:24:11Z")

</div>

Will Merrell wrote:

> belongs\_to :member  
> And this all works fine. The application can do all the CRUD functions,  
> Does anyone know how to get and display the error messages on these  
> associated tables?

Something like this?

\<% member\_phones = @member.member\_phones.find(:all, :include =\> :phone)  
for @member\_phone in member\_phones  
@phone = @member\_phone.phone  
%\>  
\<%= error\_messages\_for :member\_phone %\>  
\<%= text\_field :phone, :number %\>  
\<% end %\>

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 18, 2007, 4:04pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/5 "2007-03-18T16:04:33Z")

</div>

Mark Reginald J. wrote:

> > end  
> > has\_many :members, :through =\> :member\_phones  
> > message if I add a member with a first name of Bozo, but I can’t figure  
> > @phone = @member\_phone.phone  
> > %\>  
> > \<%= error\_messages\_for :member\_phone %\>  
> > \<%= text\_field :phone, :number %\>  
> > \<% end %\>

Hi Mark, Thanks for the reply,

Perhaps I am being dumb, but I don’t really understand how your  
suggestion helps me. When I try to use the code you supplied, it still  
fails silently. Could you explain what you expect this to do, (with a  
little background) so I can tailor it to my situation?

A word or two of background on my part may help. The way I have found to  
make the updates to the associated tables is with a supporting function  
(called update\_phones) in the member\_phones model which is called from  
the update action in the members controller. I don’t know if this is the  
proper way to do this, but it was the first thing I found that worked. I  
suppose my problem is that this technique hides the validation failures.  
Is there a more proper way to add the post parameters to the model for  
updating?

The complete member\_phones.rb file is as follows:

class MemberPhone \< ActiveRecord::Base  
belongs\_to :member  
belongs\_to :phone

validates\_presence\_of :name  
validates\_presence\_of :member\_id  
validates\_presence\_of :phone\_id  
validates\_exclusion\_of :name, :in =\> [“Foobar”], :message =\> “No  
Foobar Allowed”

before\_destroy { |record|  
if( MemberPhone.find(:all, :conditions =\> {:phone\_id =\>  
record.phone\_id}).length \< 2 )  
Phone.find(record.phone\_id).destroy  
end  
}

def update\_phone(phonename, phonenumber)  
self.name = phonename  
self.phone.number = phonenumber  
saved = self.save  
saved = self.phone.save  
return saved  
end  
end

Thanks,  
– Will  
hasmany :questions, :throught =\> :acts\_as\_nuby!

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 19, 2007, 8:15am UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/6 "2007-03-19T08:15:05Z")

</div>

Will Merrell wrote:

> Perhaps I am being dumb, but I don’t really understand how your  
> suggestion helps me. When I try to use the code you supplied, it still  
> fails silently. Could you explain what you expect this to do, (with a  
> little background) so I can tailor it to my situation?

Will, I thought your problem was how to display the errors on the  
through  
model, but I think your problem is also not preventing the update of  
both  
the phone and member\_phone if there was a validation failure on one of  
them.

You want to make sure that no record is updated if either the Phone  
or MemberPhone has errors. To do this you can add a  
validates\_associated  
directive:

class MemberPhone \< ActiveRecord::Base  
validates\_associated :phone

def update\_phone(phonename, phonenumber)  
self.name = phonename  
self.phone.number = phonenumber  
phone.save if saved = save  
return saved  
end  
end

But sometimes this is a problem because you get a “phone is invalid”  
error message in your member\_phone error list. If so, you can instead  
use:

class MemberPhone \< ActiveRecord::Base

def update\_phone(phonename, phonenumber)  
self.name = phonename  
self.phone.number = phonenumber  
valid\_phone = phone.valid?  
if valid\_combo = valid? && valid\_phone  
save(false)  
phone.save(false)  
end  
return valid\_combo  
end  
end

(For simplicity, I’m only dealing with the situation in which an  
existing  
number is updated, rather than a new number added.)

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 19, 2007, 1:46pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/7 "2007-03-19T13:46:37Z")

</div>

Will Merrell wrote:

> \<% @mphone = @member.member\_phones.find(1) %\>  
> \<%= error\_messages\_for ‘mphone’ %\> \<----- Compiles, but  
> doesn’t do anything

error\_messages\_for works on controller instance variables, so  
the above is on the right track. But when you do a find you’re  
reloading from the db, not using the objects to which your response  
handling has added errors. So I think I mislead you when in my  
original reply I used a find in the view as a shorthand to generate  
the required data structure.

So after you’ve manipulated and validated the objects in the  
member\_phone collection in the controller action, you want  
something like:

\<% @mphone = @member.member\_phones.first %\>  
\<%= error\_messages\_for :mphone %\>

or to do them all:

\<% for @mphone in @member.member\_phones  
@phone = @mphone.phone  
%\>  
\<%= error\_messages\_for :mphone %\>  
\<%= error\_messages\_for :phone %\>  
\<% end %\>

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Will\_Merrell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/4491bb/32.png) [@Will\_Merrell](https://www.ruby-forum.com/u/Will_Merrell)\
**Post date:** [March 19, 2007, 12:12pm UTC](https://www.ruby-forum.com/t/handling-validation-failures-on-hasmany-through-records/89050/8 "2007-03-19T12:12:11Z")

</div>

Mark Reginald J. wrote:

> Will, I thought your problem was how to display the errors on the through  
> model, but I think your problem is also not preventing the update of both  
> the phone and member\_phone if there was a validation failure on one of them.

Mark, Thanks for the reply and your time on this.

I agree that the code I originally posted probably had the problem you  
suggest. I was (and is) work in progress. However, that is not the  
problem I was originally asking about.

My question was, and is, how to get and display the errors when they do  
arise. The model, (when adjusted to prevent saving one when the other  
fails,) does work. If I try to enter some data that causes a validation  
failure, the record is indeed not saved. If a pepper the update\_phone  
code with logger.info calls, I can see that Phone.errors does contain  
the error messages I would expect.

My problem is I cannot find any code that I can put in the view that  
lets me display the errors.

Examples:

\<%= error\_messages\_for ‘member’ %\> \<---- This works, but only for  
failures in members

\<%= error\_messages\_for @member %\> \<---- Fails to compile  
\<%= error\_messages\_for ‘member’.member\_phones[1] %\> \<---- Fails to  
compile  
\<%= error\_messages\_for ‘member.member\_phones’ %\> \<---- Fails to  
compile  
\<%= error\_messages\_for ‘member.member\_phones[1]’ %\> \<---- Fails to  
compile  
\<%= error\_messages\_for ‘member.member\_phones.find(1)’ %\> \<---- Fails  
to compile

\<% @mphone = @member.member\_phones.find(1) %\>  
\<%= error\_messages\_for ‘mphone’ %\> \<----- Compiles, but  
doesn’t do anything

So I can raise the errors, I can control what goes into the database,  
what I can’t do is tell the user why his change was not saved!

Any ideas???

– Will
