# Validation with Aggregation

**URL:** <https://www.ruby-forum.com/t/validation-with-aggregation/69054>\
**Category:** Rails\
**Created:** [December 16, 2005, 8:18am UTC](https://www.ruby-forum.com/t/validation-with-aggregation/69054 "2005-12-16T08:18:36Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Simon\_Harris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9dc877/32.png) [@Simon\_Harris](https://www.ruby-forum.com/u/Simon_Harris)\
**Post date:** [December 16, 2005, 8:18am UTC](https://www.ruby-forum.com/t/validation-with-aggregation/69054/1 "2005-12-16T08:18:36Z")

</div>

ActiveRecord supports composed\_of for value objects which is  
fantastic but one thing that it doesn’t seem to support (or at least  
I am unable to find any documentation for) validation of the value  
objects.

For example, given the following:

class Message \< ActiveRecord::Base  
composed\_of :sender, :class\_name =\> ‘EmailAddress’  
composed\_of :recipient, :class\_name =\> ‘EmailAddress’  
…  
end

class EmailAddress  
attr\_reader :name, :address  
def initialize(name, address)  
@name, @address = name, address  
end  
…  
end

How can I best take advantage of Rails’ validation, given that I’d  
like to only specify the validation rules for EmailAddress once. The  
validation rules might look something like:

```
validates_presence_of :name, :address
validates_format_of :email, :with => ADDRESS_FORMAT

```

I’m guessing the obvious answer is to create an email\_addresses table  
and use belongs\_to but that seems (to me at least) a somewhat heave-  
handed approach.

Regards,

Simon

–  
Simon Harris  
RedHill Consulting, Pty. Ltd.  
12/55-67 Batman Street  
West Melbourne VIC Australia 3003  
[http://www.redhillconsulting.com.au](http://www.redhillconsulting.com.au)  
mob: +61 417 505 611  
yahoo/msn/skype: haruki\_zaemon  
gmail: haruki.zaemon  
icq: 20461518

---

<div class="post-metadata">

**Author:** ![Simon\_Harris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9dc877/32.png) [@Simon\_Harris](https://www.ruby-forum.com/u/Simon_Harris)\
**Post date:** [December 18, 2005, 9:53pm UTC](https://www.ruby-forum.com/t/validation-with-aggregation/69054/2 "2005-12-18T21:53:47Z")

</div>

Simon Harris wrote:

> ActiveRecord supports composed\_of for value objects which is  
> fantastic but one thing that it doesn’t seem to support (or at least  
> I am unable to find any documentation for) validation of the value  
> objects.

I’m a rails newbie struggling with the same issue. Here’s what I came  
up with:

1. Grab the ActiveForm class described here:  
[http://www.realityforge.org/articles/2005/12/02/validations-for-non-activerecord-model-objects](http://www.realityforge.org/articles/2005/12/02/validations-for-non-activerecord-model-objects)

The code is here:

[http://www.realityforge.org/files/active\_form.rb](http://www.realityforge.org/files/active_form.rb)

I used it pretty much as is, but renamed it from ActiveForm to  
ValueObject.

1. Have your value object extend ValueObject:

class PersonName \< ValueObject  
attr\_reader :first, :last, :middle  
validates\_presence\_of :first, :last

def initialize(first, middle, last)  
@first = first  
@middle = middle  
@last = last  
end  
end

Again ValueObject is the renamed version of the ActiveForm class above.  
Note that you can now use the standard validation class methods in your  
value object. (Perhaps making ValueObject a module, perhaps called  
‘Validatable’, would be better?)

1. Add a validates\_component method to the validation class methods as  
follows:

module ActiveRecord::Validations::ClassMethods  
def validates\_component(\*attr\_names)  
configuration = {}  
configuration.update(attr\_names.pop) if attr\_names.last.is\_a?(Hash)

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

```

value|  
dup\_value = value.dup  
if !dup\_value.valid?  
dup\_value.errors.each { |attr, msg|  
record.errors.add(“#{attr\_name}\_#{attr}”, msg) }  
end  
end  
end  
end

You can now use validates\_component(:name) in your ActiveRecord objects  
to trigger validation of composed\_of aggregates. It’s a bit tedious  
though to write both the composed\_of and validates\_component  
declarations, so:

1. Add a composed\_of\_and\_validates method to the validation class  
methods:

module ActiveRecord::Aggregations::ClassMethods  
def composed\_of\_and\_validates(part\_id, options = {})  
composed\_of(part\_id, options)  
validates\_component(part\_id)  
end  
end

You can then write an ActiveRecord object that validates its components  
like this:

class Person \< ActiveRecord::Base  
composed\_of\_and\_validates :name,  
:class\_name =\> PersonName,  
:mapping =\> [  
[:first\_name, :first],  
[:middle\_name, :middle],  
[:last\_name, :last]  
]

end

---

<div class="post-metadata">

**Author:** ![Simon\_Harris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9dc877/32.png) [@Simon\_Harris](https://www.ruby-forum.com/u/Simon_Harris)\
**Post date:** [December 18, 2005, 11:20pm UTC](https://www.ruby-forum.com/t/validation-with-aggregation/69054/3 "2005-12-18T23:20:29Z")

</div>

Simon Harris wrote:

> ActiveRecord supports composed\_of for value objects which is  
> fantastic but one thing that it doesn’t seem to support (or at least  
> I am unable to find any documentation for) validation of the value  
> objects.

I’m a rails newbie struggling with the same issue. Here’s what I came  
up with:

1. Grab the ActiveForm class described here:  
[http://www.realityforge.org/articles/2005/12/02/validations-for-non-activerecord-model-objects](http://www.realityforge.org/articles/2005/12/02/validations-for-non-activerecord-model-objects)

The code is here:

[http://www.realityforge.org/files/active\_form.rb](http://www.realityforge.org/files/active_form.rb)

I used it pretty much as is, but renamed it from ActiveForm to  
ValueObject.

1. Have your value object extend ValueObject:

class PersonName \< ValueObject  
attr\_reader :first, :last, :middle  
validates\_presence\_of :first, :last

def initialize(first, middle, last)  
@first = first  
@middle = middle  
@last = last  
end  
end

Again ValueObject is the renamed version of the ActiveForm class above.  
Note that you can now use the standard validation class methods in your  
value object. (Perhaps making ValueObject a module, perhaps called  
‘Validatable’, would be better?)

1. Add a validates\_component method to the validation class methods as  
follows:

module ActiveRecord::Validations::ClassMethods  
def validates\_component(\*attr\_names)  
configuration = {}  
configuration.update(attr\_names.pop) if attr\_names.last.is\_a?(Hash)

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

```

value|  
dup\_value = value.dup  
if !dup\_value.valid?  
dup\_value.errors.each { |attr, msg|  
record.errors.add(“#{attr\_name}\_#{attr}”, msg) }  
end  
end  
end  
end

You can now use validates\_component(:name) in your ActiveRecord objects  
to trigger validation of composed\_of aggregates. It’s a bit tedious  
though to write both the composed\_of and validates\_component  
declarations, so:

1. Add a composed\_of\_and\_validates method to the validation class  
methods:

module ActiveRecord::Aggregations::ClassMethods  
def composed\_of\_and\_validates(part\_id, options = {})  
composed\_of(part\_id, options)  
validates\_component(part\_id)  
end  
end

You can then write an ActiveRecord object that validates its components  
like this:

class Person \< ActiveRecord::Base  
composed\_of\_and\_validates :name,  
:class\_name =\> PersonName,  
:mapping =\> [  
[:first\_name, :first],  
[:middle\_name, :middle],  
[:last\_name, :last]  
]

end

---

<div class="post-metadata">

**Author:** ![Simon\_Harris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9dc877/32.png) [@Simon\_Harris](https://www.ruby-forum.com/u/Simon_Harris)\
**Post date:** [December 18, 2005, 11:20pm UTC](https://www.ruby-forum.com/t/validation-with-aggregation/69054/4 "2005-12-18T23:20:37Z")

</div>

Stephen M. wrote:

> ```
> dup_value = value.dup
> if !dup_value.valid?
> dup_value.errors.each { |attr, msg| 
> 
> ```
> 
> record.errors.add("#{attr\_name}\_#{attr}", msg) }  
> end  
> end  
> end  
> end

One thing I forgot to mention is the reason for the call to value.dup  
above. ActiveRecord freezes value objects once they are attached to an  
ActiveRecord object. However validate and valid? change the state of  
the object when they add to its errors collection. So without the call  
to dup you’d get a “can’t modify frozen object” error.

The weird thing about this approach then is that you can call valid? on  
your value object _before_ assigning it to its owner, but not  
afterwords:

name = PersonName.new(‘Tom’, ‘T’, ‘Hall’)

# this is OK:

name.valid?

# Person is an active record object composed\_of a name:

person = Person.new  
person.name = name

# this will blow up:

name.valid? # attempt to modify frozen object  
name.dup.valid? # this is OK

Steve
