# Custom Validation on Many-To-Many Association breaks Unit-Tests

**URL:** <https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661>\
**Category:** Rails\
**Created:** [April 28, 2009, 10:29am UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661 "2009-04-28T10:29:51Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 10:29am UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/1 "2009-04-28T10:29:51Z")

</div>

Hi, I have the following situation. I have two models Item and Genre.  
A Item has a name and a description. The genres-table contains a list  
of possible genres wich can be associated to items. So a Item could be  
associated with many genres and a genre could be associated with many  
items. A typically n:m-relationship. I use the :has\_many-:through  
association, because i want do to a kind of on-delete-cascade in  
Rails.  
My models look as follows:

class Item \< ActiveRecord::Base

# n:m relationship between items and genres

has\_many :items\_genres, :dependent =\> :destroy  
has\_many :genres, :through =\> :items\_genres

validates\_presence\_of :name

validate :must\_have\_at\_least\_one\_associated\_genre

protected

# valdation to ensure, that a item has at least one associated genre

def must\_have\_at\_least\_one\_associated\_genre  
# add an error message to the default error messages  
errors.add(:genres, “must\_be\_choosen”) if  
# if no genre is associated with this item  
genres.size \<= 0  
end

end

I put two validations to the Item. The statement at line 6 make the  
name arrtibute mandatory. In addition I would to ensure that a item  
has at least one associated genre. So I decided to write a own  
validation-method (line 10-17).

class ItemsGenre \< ActiveRecord::Base  
belongs\_to :item  
belongs\_to :genre  
end

class Genre \< ActiveRecord::Base

# n:m relationship between genres and items

has\_many :items\_genres, :dependent =\> :destroy  
has\_many :items, :through =\> :items\_genres  
end

I added some unit-tests to ensure that the validation works as  
aspected. I wrote the following unit-test-methods.

require ‘test\_helper’

class ItemTest \< ActiveSupport::TestCase

def test\_should\_create\_an\_item  
item = Item.new(  
:name =\> “Item-Name”,  
:description =\> “Item-Description”  
)

```
# Assert, that the item is not valid and cannot be saved,
# because there are no genres associated with it
assert !item.valid?
assert !item.save

# Associate two genres with this item
item.genres = Genre.find_all_by_id([genres(:club).id, genres

```

(:commedy).id])

```
# Assert, that the item is now valid and can be saved
assert item.valid?
assert item.save

# Check if there are two genres associated with this item
assert_equal 2, item.genres.size

```

end

def test\_should\_require\_name  
# Create an item-object, but set name nil  
item = Item.new(  
:name =\> nil,  
:description =\> “Item-Description”  
)  
# Assert, that the item is not valid and cannot be saved,  
# because the name is nil  
assert !item.valid?  
assert !item.save  
end

def test\_should\_require\_description  
# Create an item-object, but set name to nil  
item = Item.new(  
:name =\> “Item-Name”,  
:description =\> nil  
)  
# Assert, that the item is not valid and cannot be saved,  
# because the description is nil  
assert !item.valid?  
assert !item.save  
end

end

The amazing thing is that all tree test-methods pass. But I only have  
a validation for the name and the asscociated genres. I do not have a  
validation of the description, but the test method for the description  
passes.

I found out another thing. If I remove the validate-call in line 8 of  
the Item-model, then all test-methods work as aspected.  
In this case the test\_should\_create\_an\_item- and the  
test\_should\_require\_description-method both fail and the  
test\_should\_require\_name-method passes.

If I run the application and try to add a new item by the new-form,  
all validation works as exspected. So it seems that only the unit-test  
are faulty.

I am at a loss. I don´t know what I am doing wrong. Can anyone  
reproduce this behavior? Or can anyone tell me how to write a  
validation-method to ensure that at least one genre is associated with  
an item. Maybe my test-method is wrong.

I hope someone can help me out.

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 10:33am UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/2 "2009-04-28T10:33:22Z")

</div>

On Apr 28, 9:25 am, zeto [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> assert !item.save
> 
> ```
> 
> end
> 
> end
> 
> The amazing thing is that all tree test-methods pass. But I only have  
> a validation for the name and the asscociated genres. I do not have a  
> validation of the description, but the test method for the description  
> passes.

In your test that description should be required you haven’t created  
any genres, so even though you have no validation for description the  
validation on genres being present makes the item fail to save.

Fred

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 2:43pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/3 "2009-04-28T14:43:56Z")

</div>

At first, thank you for your advise. I forgot to associate genres in  
the description\_should\_be\_required-test-method. And you are right.  
This test method should fail, but it surprisingly passes.

zeto

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 3:21pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/4 "2009-04-28T15:21:38Z")

</div>

You can always go into must\_have\_at\_least\_one\_associated\_genre with the  
debugger and find out why it is not failing.

2009/4/28 zeto [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 4:03pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/5 "2009-04-28T16:03:59Z")

</div>

It is not the must\_have\_at\_least\_one\_associated\_genre-test-method. The  
test\_should\_require\_description-test-method passes the test, but that  
method should fail.

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 4:49pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/6 "2009-04-28T16:49:25Z")

</div>

If I understand correctly you are saying that  
test\_should\_require\_description is passing when it should fail. The  
fact  
that it passes appears to mean that the item is not valid. The question  
is  
why is it not valid? It may be that  
must\_have\_at\_least\_one\_associated\_genre  
is failing. I would check that first. You could just remove this  
validation to eliminate it.

2009/4/28 zeto [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 4:58pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/7 "2009-04-28T16:58:16Z")

</div>

If I comment out the validation  
“validate :must\_have\_at\_least\_one\_associated\_genre” in line 8 of my  
Item-model all test methods work correctly. That means only the  
test\_should\_require\_name -test-method passes the test.

test\_should\_create\_an\_item --\> fails, because the validation in  
line 8 of my Item-model is commented out  
test\_should\_require\_description --\> fails, because there is no  
validation for description yet

Of course the failure is somewhere in the  
must\_have\_at\_least\_one\_associated\_genre-method in the Item-model, but  
I cannot figure out where the failure is.

---

<div class="post-metadata">

**Author:** ![zeto](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/9f8e36/32.png) [@zeto](https://www.ruby-forum.com/u/zeto)\
**Post date:** [April 28, 2009, 6:30pm UTC](https://www.ruby-forum.com/t/custom-validation-on-many-to-many-association-breaks-unit-tests/166661/8 "2009-04-28T18:30:56Z")

</div>

Go in with the debugger and have a look at the objects.

2009/4/28 zeto [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
