app/models/email_address.rb in has_emails-0.0.1 vs app/models/email_address.rb in has_emails-0.1.0
- old
+ new
@@ -1,123 +1,45 @@
# Represents a valid RFC822 email address
class EmailAddress < ActiveRecord::Base
+ has_emails
+
+ validates_presence_of :spec
+ validates_as_email_address :spec
+ validates_uniqueness_of :spec,
+ :scope => 'name'
+
class << self
- # Converts the specified record to an EmailAddress. It will convert the
- # following types:
- # 1. String
- # 2. A record with an +email_address+ String attribute
- # 3. A record with an +email_address+ association
- # 4. A record with an +email_addresses+ association (first record will be chosen)
- #
- # If an EmailAddress is specified, the same model will be returned. An
- # ArgumentError is raised if it doesn't match any of the above criteria.
- def convert_from(record)
- if record
- if EmailAddress === record
- record
- elsif String === record
- EmailAddress.new(:spec => record)
- elsif record.respond_to?(:email_address)
- if record.email_address.is_a?(String)
- address = EmailAddress.new(:spec => record.email_address)
- address.name = record.name if record.respond_to?(:name)
- address
- else
- record.email_address
- end
- elsif record.respond_to?(:email_addresses)
- record.email_addresses.first
- else
- raise ArgumentError, "Cannot convert #{record.class} to an EmailAddress"
- end
- end
+ # Finds or create an email address based on the given value
+ def find_or_create_by_address(address)
+ name, spec = split_address(address)
+ find_or_create_by_name_and_spec(name, spec)
end
- # Determines if the given spec is a valid address using the RFC822 spec
- def valid?(spec)
- !RFC822::EmailAddress.match(spec).nil?
+ # Splits the given address into a name and spec
+ def split_address(address)
+ if match = /^(\S.*)\s+<(.*)>$/.match(address)
+ name = match[1]
+ spec = match[2]
+ else
+ spec = address
+ end
+
+ return name, spec
end
end
- acts_as_tokenized :token_field => 'verification_code', :token_length => 32
-
- # Support e-mail address verification
- has_states :initial => :unverified
-
- # Add messaging capabilities. This will give us an email_box.
- has_messages :emails,
- :message_class => 'Email'
- belongs_to :emailable,
- :polymorphic => true
-
- validates_presence_of :spec
-
- with_options(:allow_nil => true) do |klass|
- klass.validates_uniqueness_of :spec
- klass.validates_as_email_address :spec
+ # Sets the value to be used for this email address. This can come in two formats:
+ # * With name - John Doe <john.doe@gmail.com>
+ # * Without name - john.doe@gmail.com
+ def address=(address)
+ self.name, self.spec = self.class.split_address(address)
end
- # The name of the person who owns this email address
- attr_accessor :name
-
- # Ensure that the e-mail address has a verification code that can be sent
- # to the user
- before_create :set_code_expiry
-
- state :unverified, :verified
-
- # Verifies that the email address is valid
- event :verify do
- transition_to :verified, :from => :unverified
- end
-
- # Sets the full address
- def spec=(new_spec)
- @local_name = @domain = nil
- write_attribute(:spec, new_spec)
- end
-
- # The part of the e-mail address before the @
- def local_name
- parse_spec if !@local_name
- @local_name
- end
-
- # The part of the e-mail address after the @
- def domain
- parse_spec if !@domain
- @domain
- end
-
- # Gets the name of the person whose email address this is. Default is an
- # empty string. Override this if you want it to appear in with_name
- def name
- @name || ''
- end
-
- # Returns a string version of the email address plus any name like
- # "John Doe <john.doe@gmail.com>". In order to have a valid name within the
- # string, you must override +name+.
+ # Generates the value for the email address, including the name associated with
+ # it (if provided). For example,
+ #
+ # e = EmailAddress.new(:name => 'John Doe', :spec => 'john.doe@gmail.com')
+ # e.with_name # => "John Doe <john.doe@gmail.com>"
def with_name
- name.blank? ? to_s : "#{name} <#{to_s}>"
- end
-
- # Returns the full email address (without the name)
- def to_s #:nodoc
- spec
- end
-
- private
- # Sets the time at which the verification code will expire
- def set_code_expiry
- self.code_expiry = 48.hour.from_now
- end
-
- # Parses the current spec and sets +@local_name+ and +@domain+ based on the
- # matching groups within the regular expression
- def parse_spec
- if !@local_name && !@domain && match = RFC822::EmailAddress.match(spec)
- @local_name = match.captures[0]
- @domain = match.captures[1]
- end
+ name.blank? ? spec : "#{name} <#{spec}>"
end
end