开发者

rails 3 validation for a comma-separated list of email addresses

I'm a total newbie at Rails validation, and while I've seen some related questions, I cannot figure how to extend them to my situation.

I need to allow a user setting up their account to enter up 开发者_如何学运维to N (a system wide constant, like 10) optional email addresses.

so the data a user would enter into the text field might look like

foo@bar.com

or

foo@bar.com, foo2@bar2.com,foo3@bar3.com , foobar4@domain.com

(note inconsistent use of space before or after comma, typical real-user stuff)

currently in my model I handle single optional email and use a regex :

validates :alert_email,
    :allow_blank => true,
    :length => {:minimum => 3, :maximum => 254},
    :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}

There is probably some sort of uber-regex that I could replace mine with... and that would be fine if anyone can help. However for readability (and because performance is irrelevant since this is done once per user) I think I should somehow move the validation to a method that brute force parses them out and runs the regex one at a time?

PS I would also like my validation routine to "fix up" the space/comma thing, so it's always comma-space between items in the list, and have that fixed-up version be what's saved. I'm guessing I do some before_xxxxx method?


You can use the Ruby split method to separate your list of emails into an array and the join method to save them back into a common format.

before_validation do
  emails = self.emails.split(/\s+,\s+/)

  emails.each do |email|
    self.errors.add(:emails, "invalid email") unless email =~ /([^\s]+)@([^\s]+)/ 
  end

  self.emails = emails.join(",")
end


In your form you can submit a collection of values if you use a format like this:

&optional_email[]=email1@example.com&optional_email[]=email2@example.com

You would represent this in your form like:

Email 1: <%= text_field_tag 'optional_email[]' %>
Email 2: <%= text_field_tag 'optional_email[]' %>   

These also work with the model helpers etc.

Then rails will figure out how to turn those parameters into a collection like:

params[:optional_email] = ['email1@example.com', 'email2@example.com']

If you can't do that, an alternative would be splitting this yourself inside your controller:

@model.optional_emails = params[:optional_email].split(/[\,]/).map(&:strip)

Then in either case you can write a validation that works on each individual email without using a huge regex.

Depending how your data is being used you may be better served with a model for emails. If you have a reason not to do that you could use the serialize method on your model to ensure this field is always a collection of emails.


validates :daily_recipients,
   :format => { :with => /(\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})(,\s*([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,}))*\z)/i },
   :allow_blank => true


By keeping all of those email addresses in a single field you are losing a lot of the power of Rails. There are oodles of methods that help with set operations, finding, validating, associating, etc., that you will miss out on or have to implement yourself. This question is just an example of that. The rails way to do this is to create a separate model for these emails, store them there one record per email, and associate that model with your Account model.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜