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 ;-) ) 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
Mark Reginald James
2005-Dec-17 04:24 UTC
Re: How to use validation with aggregation (composed_of)?
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.