# Validating associated objects

**URL:** <https://www.ruby-forum.com/t/validating-associated-objects/108424>\
**Category:** Rails\
**Created:** [July 3, 2007, 11:11am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424 "2007-07-03T11:11:31Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 3, 2007, 11:11am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/1 "2007-07-03T11:11:31Z")

</div>

I am having a weird problem

class Post  
has\_many :uploads  
end

class Upload  
belongs\_to :post  
end

In the form in my view the user can upload multiple files at once. In  
my model  
there are multiple validations for an Upload, such as being under a  
certain filesize or not having absurd dimensions if it’s an image, etc.

The problem is that if one of the uploads fails validation, the Post  
object fails validation as well. Previously, I thought I had to specify  
validates\_associated :uploads in the Post model to get this behavior,  
but seems like that is not the case. If one of the uploads fails I get  
the error message “Uploads is invalid” in the Post object’s errors,  
which prevents the Post and all other Uploads from saving whether or not  
they are valid; so basically one bad upload ruins the whole thing. This  
is kind of bad since it can take a user a while to upload multiple  
files, and I think it’s silly to say “one upload out of ten failed,  
start all over” when some of the uploads might be good.

What I would -like- to do is accept as many uploads as possible, having  
the Post object fail to save only if zero uploads were valid. Any  
invalid uploads get thrown away (although ideally I could somehow keep  
their errors stored somewhere [in the Post object?] so I can show the  
user what uploads failed and why).

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 4, 2007, 6:39am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/2 "2007-07-04T06:39:13Z")

</div>

Bumping this before it fades into obscurity forever.

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 4, 2007, 7:33am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/3 "2007-07-04T07:33:16Z")

</div>

R. Elliott M. wrote:

> In the form in my view the user can upload multiple files at once. In  
> they are valid; so basically one bad upload ruins the whole thing. This  
> is kind of bad since it can take a user a while to upload multiple  
> files, and I think it’s silly to say “one upload out of ten failed,  
> start all over” when some of the uploads might be good.
> 
> What I would -like- to do is accept as many uploads as possible, having  
> the Post object fail to save only if zero uploads were valid. Any  
> invalid uploads get thrown away (although ideally I could somehow keep  
> their errors stored somewhere [in the Post object?] so I can show the  
> user what uploads failed and why).

The file\_column plugin, and perhaps other file upload plugins,  
will automatically store the valid uploads in temporary files  
so that they do not have to be uploaded again when the form  
is re-presented.

But if you want the partial save to proceed you’ll have to  
loop through the upload params, creating upload objects,  
calling valid? on them, and adding them to the post’s uploads  
collection if valid and to a reject array if not, then  
saving the post (along with the valid uploads) if at least one  
upload is valid. Re-present the invalid uploads to the user.

If you still need to get rid of the automatic associate validity  
check that is causing your “Uploads is invalid” message, just add:

```
  class Post
    validate_associated_records_for_uploads() end
  end

```

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

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 4, 2007, 8:42am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/4 "2007-07-04T08:42:18Z")

</div>

Had no idea such a method would exist. Thanks, I’ll try it out.

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 5, 2007, 8:53am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/5 "2007-07-05T08:53:46Z")

</div>

Hm, the problem I’m finding in this approach is that validation is being  
called twice; once when I call valid? for the object and a second time  
before the Post is saved. This wouldn’t be too much of an issue if my  
validations didn’t require database queries to be run, but unfortunately  
because they are run it causes an unnecessary about of redundancy.

I would use file\_column but I think I might be too far along in  
development for that. Maybe I should just try to mimic how it saves  
files temporarily before re-presenting the form. I just figured if a  
user makes an invalid upload, the upload is probably going to stay  
invalid.

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 7, 2007, 1:39am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/6 "2007-07-07T01:39:25Z")

</div>

It seems like the uploads, associated with the post, are being validated  
as the post is saved. Both the post and its associated objects having  
not been saved, all the objects go through their validations, which  
makes sense I guess. Overriding the  
validate\_associated\_records\_for\_uploads method prevents the validation  
from being run twice, but as each upload object is saved, it is  
validated.

I tried to instead use your save(false) method and save the uploads  
-before- I saved the post object, after calling valid? on those objects.  
I separated the good uploads from the bad and left the bad in the Post  
object as post.bad\_uploads. However, saving the uploads ahead of time  
didn’t work out well either. Validation was still run as the post  
object was saved.

I could try to save the post and upload completely separate from each  
other but the problem is their validations are related. A post  
shouldn’t be saved if its uploads are bad, and an upload shouldn’t be  
saved if the post is bad, so it’s turning out to be somewhat of a mess.

So overriding validate\_associated\_records\_for\_uploads() just really  
prevents validation from being run THREE times in my case (once with  
that method, once with valid? and a third time when the post is saved.)

I guess I can try to use file\_column and perhaps modify it to suit my  
needs.

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 10, 2007, 6:40pm UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/7 "2007-07-10T18:40:15Z")

</div>

R. Elliott M. wrote:

> I separated the good uploads from the bad and left the bad in the Post  
> prevents validation from being run THREE times in my case (once with  
> that method, once with valid? and a third time when the post is saved.)

Yes, Rails 1.2 incorrectly runs validation twice on cascaded  
saves, even if the parent object is saved with save(false)  
or save\_without\_validation. Blocking the validate\_associated\_records…  
method gets rid of one, but each new child will still be validated  
before it’s inserted into the DB.

To avoid this you have to do your own save cascade: save the  
parent using save(false)/save\_without\_validation without any  
new children added to its collections. Then separately build  
and save each child the same way.

To save only if everything’s valid you have to first run valid?  
on each record.

if post.valid? && uploads.inject(true) { |v, u| u.valid? && v }  
post.save(false)  
uploads.each { |u| u.post = post; u.save(false) }  
end

This can be simplified if post is not a new record.

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

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 19, 2007, 11:26am UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/8 "2007-07-19T11:26:45Z")

</div>

I seem to have figured it out with your help. I’d post the code but  
it’s disturbingly tacky, but at least it gets the job done. I don’t  
think there’s anymore room for elegance with what I have.

Maybe I can later figure out how to do the temporary file save for  
re-presenting the form to the user, but I’m guessing the code behind  
that isn’t exactly trivial.

---

<div class="post-metadata">

**Author:** ![RSElliott\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@RSElliott\_M](https://www.ruby-forum.com/u/RSElliott_M)\
**Post date:** [July 6, 2007, 4:37pm UTC](https://www.ruby-forum.com/t/validating-associated-objects/108424/9 "2007-07-06T16:37:55Z")

</div>

R. Elliott M. wrote:

> Hm, the problem I’m finding in this approach is that validation is being  
> called twice; once when I call valid? for the object and a second time  
> before the Post is saved. This wouldn’t be too much of an issue if my  
> validations didn’t require database queries to be run, but unfortunately  
> because they are run it causes an unnecessary about of redundancy.

save(false) saves without validation; and the automatic validation  
of has\_many associates can be turned off in the way described in  
my last post.

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