How to use validation with aggregation (composed_of)?

At the risk of being banned for posting the same question twice, I
thought I’d try once more with a question for the title rather than a
statement (on the basis that perhaps questions get answered and
statements ignored :wink: )

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
mob: +61 417 505 611
yahoo/msn/skype: haruki_zaemon
gmail: haruki.zaemon
icq: 20461518

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.

Here’s an attempt at a solution. Any better way?

class Message < ActiveRecord::Base
composed_of :sender, :class_name => ‘EmailAddress’,
:mapping => [[:sender_name], [:sender_address]]

composed_of :recipient, :class_name => ‘EmailAddress’,
:mapping => [[:recipient_name], [:recipient_address]]

def validate
[‘sender’, ‘recipient’].each do |attr|
obj = self.send(attr)
[‘name’, ‘address’].each do |field|
msg = obj.send(“valid_#{field}?”)
# choose one of the following
errors.add_to_base( “#{attr}'s #{field} #{msg}” ) unless
msg.blank?
errors.add( “#{attr}_#{field}”, msg ) unless msg.blank?
end
end
super
end
end

class EmailAddress
attr_reader :name, :address

def initialize( name, address )
@name, @address = name, address
end

def valid_address?
@valid_address ||=
check_valid?( @address ) ? ‘’ : ‘is not a valid email address’
end

def valid_name?
@valid_name ||=
if @name.blank?
‘cannot be blank’
elsif @name =~ /[A-Za-Z][A-Za-z -]*/
‘’
else
‘contains invalid characters’
end
end
end


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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs