views:

636

answers:

4

In the current app I'm building I've got a textarea where a user will enter a comma-delimited list of email addresses.

I'm currently splitting the list into an array and then saving one by one. But if, say, I have this input...

[email protected], test@example, [email protected]

... then [email protected] will be saved, but saving test@example will fail. So I then need to remove [email protected] from the comma-delimited string of values that I pass back to the textarea when I show the error that test@example isn't a valid email address.

Is there a better way to validate these on the server side and handle errors without getting fancy / ugly in the controller?

Thanks in Advance!

A: 

If you have them in a variable called emails, perhaps something like this may work:

  if valid_emails?(emails)
      # then have your normal logic here
      if @user.save
           flash[:notice] .....

      end
  end

  private
     def valid_emails?(emails)
        not emails.find {|email| email =~ /[\w\.%\+\-]+@(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)/i }.nil?
     end

EDIT: actually you may just want to use this regular expression. It was taken from the restful-authentication plugin.

vrish88
A: 

ruby has a split function (.each) described here and supports regular expressions as described here

as such, you'd split the string (using "," as your separator) and then use the regular expression to validate each e-mail.

SnOrfus
A: 

You can put saving emails in transaction. Then if any save will fail, then all previos saves are canceled. In such case, validations can be done only on model layer.

I think it would be clear code, but for sure it isn't the fastest possible way (but using Ruby means you are not doing it in even fast way ;) )

klew
A: 

Assuming this is a model that has_many emails, and the email model uses :validate_email, you could do something like the following:

class Foo < ActiveRecord::Base
  validate :must_not_have_invalid_addresses

  ...

  def emails=(addresses)
    @invalid_addresses = []
    addresses.split(",").each do |address|
      @invalid_addresses.push(address) unless emails.create({:address => address})
    end
  end

  def must_not_have_invalid_addresses
    errors.add_to_base("Some email addresses were invalid") unless @invalid_addresses.empty?
  end

end

This provides a validation error + an array of the invalid email addresses which you can make accessible to your view if you like.

dbarker