# Dead horse: validates\_associated

**URL:** <https://www.ruby-forum.com/t/dead-horse-validates-associated/63281>\
**Category:** Rails\
**Created:** [June 13, 2006, 9:04pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281 "2006-06-13T21:04:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 9:04pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/1 "2006-06-13T21:04:35Z")

</div>

Regarding validates\_associated…

Let’s say I have:  
article belongs\_to author  
But for whatever reason, I want an article to also be written  
anonymously and therefore not require an author. Then I have:

Article:  
belongs\_to :author  
validates\_associated :author

But I DON’T have validates\_presence\_of. What I want to do is validate  
that an author is valid --if it is specified–.

- I want to allow for the case where article.author\_id = nil.
- I DO NOT want to allow for the case where article.author\_id =  
SOME\_INVALID\_ID

During testing, I tried this:  
article = Article.new  
article.author\_id = nil  
assert c.valid? (True – working so far)  
article.author\_id = 5  
assert c.valid? (True – because author 5 is valid)  
article.author\_id = 999  
assert c.valid? (True!?! – shouldn’t be!)

So, how can one protect for the case where the associated link doesn’t  
refer to an existing database row at all?

Can someone give me an example of a successful use of  
validates\_associated that is NOT coupled to validates\_presence\_of?  
Afterall, it seems quite pointless to have validates\_associated if it  
returns true for an object that isn’t even in the database.

Jake

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 10:03pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/2 "2006-06-13T22:03:33Z")

</div>

Go here, and look at the if option  
[http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000820](http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000820)

-Nick

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 10:07pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/3 "2006-06-13T22:07:22Z")

</div>

Nick S. wrote:

> Go here, and look at the if option  
> [Peak Obsession](http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html#M000820)
> 
> -Nick

Yes, I considered that. Are you suggesting something like:

validates\_presence\_of :article, :if =\> Proc.new { |c|  
!c.article\_id.nil? }

Jake

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 10:23pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/4 "2006-06-13T22:23:33Z")

</div>

On Tuesday, June 13, 2006, at 9:04 PM, Jake J. wrote:

> assert c.valid? (True – working so far)  
> Afterall, it seems quite pointless to have validates\_associated if it  
> returns true for an object that isn’t even in the database.
> 
> Jake
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)

Oddly enough, I just encounted that problem myself. I am in the process  
of testing a plugin that fixes the behavior of validates\_associated so  
that it detects invalid entries…

Here it is… should work in most cases, but I haven’t completely tested  
it. YMMV.

from the console,  
script/generate plugin validates\_associated  
put this in the lib folder and then add  
require ‘validates\_associated’ in the init.rb file.  
Restart your server and you’re off.

module ActiveRecord  
module Validations  
module ClassMethods

```
  # Checks associated object to ensure validity according to

```

ActiveRecord standards  
# Will not fail if the association is not defined, use  
validates\_presence\_of to ensure  
# a foreign key exists, if necessary. This validation will fail  
if an associated object is invalid  
# or if a foreign key points to a non-existent record.  
def validates\_associated(\*attr\_names)  
configuration = { :message =\>  
ActiveRecord::Errors.default\_error\_messages[:invalid], :on =\> :save }  
configuration.update(attr\_names.pop) if  
attr\_names.last.is\_a?(Hash)

```
     validates_each(attr_names, configuration) do |record,

```

attr\_name, value|  
reflection = self.reflect\_on\_association(attr\_name)  
if reflection.macro == :belongs\_to  
class\_to\_check = reflection.options[:polymorphic] ?  
record.send(reflection.options[:foreign\_type]).constantize :  
reflection.active\_record  
unless record.send(reflection.primary\_key\_name).blank? &&  
class\_to\_check.exists?(record.send(reflection.primary\_key\_name))  
record.errors.add(attr\_name,configuration[:message])  
end  
end  
record.errors.add(attr\_name, configuration[:message]) unless  
(value.is\_a?(Array) ? value : [value]).all? { |r| r.nil? or  
r.valid? }  
end  
end  
end  
end  
end

\_Kevin

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 10:28pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/5 "2006-06-13T22:28:41Z")

</div>

Kevin O. wrote:

> Oddly enough, I just encounted that problem myself. I am in the process  
> of testing a plugin that fixes the behavior of validates\_associated so  
> that it detects invalid entries…
> 
> Here it is… should work in most cases, but I haven’t completely tested  
> it. YMMV.

Thanks Kevin. I may use the plugin. Really, it was a safety measure –  
afterall, my “invalid entries” should have been deleted with proper  
has\_many and belongs\_to setups. And other things are wrong if it gets  
to this point.

I’m still curious – was the original behavior to be expected? Was this  
how Rails was designed? If so, is there a reason for it?

Jake

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 11:00pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/6 "2006-06-13T23:00:58Z")

</div>

Kevin O. wrote:

> My personal spin on this is that the association should be invalid IF  
> the associated record is invalid AND if the association link is invalid.
> 
> In most cases, it won’t be an issue because active record is pretty good  
> at cleaning up after itself, but you never know. This is kind of a  
> belt-and-suspenders type of patch. It’s more likely to show up as a  
> problem during development than in live code.
> 
> \_Kevin

Yes. I completely agree.

---

<div class="post-metadata">

**Author:** ![janovetz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/53a042/32.png) [@janovetz](https://www.ruby-forum.com/u/janovetz)\
**Post date:** [June 13, 2006, 10:48pm UTC](https://www.ruby-forum.com/t/dead-horse-validates-associated/63281/7 "2006-06-13T22:48:14Z")

</div>

On Tuesday, June 13, 2006, at 10:28 PM, Jake J. wrote:

> has\_many and belongs\_to setups. And other things are wrong if it gets  
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)

Incidentally, here’s the ticket I opened on this recently.  
[http://dev.rubyonrails.org/ticket/5369](http://dev.rubyonrails.org/ticket/5369)

The original behavior is to flag an association as invalid IF and ONLY  
IF the associated object is invalid (via activerecord). If there is no  
associated record, it is not flagged as invalid. If the foreign key is  
invalid, it won’t trigger either.

My personal spin on this is that the association should be invalid IF  
the associated record is invalid AND if the association link is invalid.

In most cases, it won’t be an issue because active record is pretty good  
at cleaning up after itself, but you never know. This is kind of a  
belt-and-suspenders type of patch. It’s more likely to show up as a  
problem during development than in live code.

\_Kevin
