Regex, size check inside a Controller's method.

Hello, I'm working to create a method in my controller to check an email to see if the email's domain is acceptable. I want to prevent gmail and hotmail for certain reasons. Here's what I have so far:

controller:     if valid_email_domain(email_address)       # good email domain     else       # bad email domain     end

protected   def valid_email_domain(emailAddy)     reg = Regexp.new '/#{User::INVALID_EMAILS.map{|a| Regexp.quote(a)}.join("|")}/'     return true if emailAddy.scan(reg).size == 0   end

user model: INVALID_EMAILS = %w(gmail.com hotmail.com)

But that errors, any ideas? I'm not sure if I'm doing the REGEX correctly, could use some regex help.

CuriousNewbie wrote in post #976445:

Hello, I'm working to create a method in my controller to check an email to see if the email's domain is acceptable. I want to prevent gmail and hotmail for certain reasons. Here's what I have so far:

controller:     if valid_email_domain(email_address)       # good email domain     else       # bad email domain     end

protected   def valid_email_domain(emailAddy)     reg = Regexp.new '/#{User::INVALID_EMAILS.map{|a| Regexp.quote(a)}.join("|")}/'     return true if emailAddy.scan(reg).size == 0   end

user model: INVALID_EMAILS = %w(gmail.com hotmail.com)

But that errors, any ideas?

And the error you get is...?

I'm not sure if I'm doing the REGEX correctly, could use some regex help.

Well, your regex seems OK, but you should be doing your validation in the model, not the controller.

Best,

First, I agree with Marnen that this should be done in the model but I disagree that the regexp is formed correctly on a very minor point; you don't need to add the '/' inside the quotes when building a new regexp object i.e. Regexp.new('some regexp') rather than Regexp.new('/ some regexp/').

So what I would do in the model is:

class User < AR::B   INVALID_EMAILS = %w(gmail.com hotmail.com)   def self.valid_email?(email)      reg = Regexp.new(INVALID_EMAILS*'|') # *'string' is an alias for .join('string') use whichever you preffer      matches = reg.match(email)      return matches == 0   end end

Then in the controller you can do

def some_action   if User.valid_email?(params[:email])     #do stuff   else     #do other stuff   end end

This has the added benefits that you can use this same validation anywhere in your code and easily add additional conditions to your validation in a single place.

-T

class User < AR::B INVALID_EMAILS = %w(gmail.com hotmail.com) def self.valid_email?(email) reg = Regexp.new(INVALID_EMAILS*'|') # *'string' is an alias for .join('string') use whichever you preffer matches = reg.match(email) return matches == 0 end end

A couple additional notes: The logical test ('matches == 0') should actually be 'matches.size == 0'. Also, unless you are going to change your INVALID_EMAILS array at runtime you could generate the regexp on application boot preventing it from having to be created every time you run the code. This is a premature optimization but it is also a valid way of doing things. Also you can do the logical test on the same line turning #valid_email? into a one liner.

So the user class would look something like this now:

class User < AR::B INVALID_EMAILS = %w(gmail.com hotmail.com)   INVALID_EMAIL_REGEXP = Regexp.new(INVALID_EMAILS*'|') def self.valid_email?(email) return INVALID_EMAIL_REGEXP.match(email).size == 0 end end

Another note (last one... maybe) you could use empty? instead of size but you'd have to negate the result i.e.: return !INVALID_EMAIL_REGEXP.match(email).empty?

t.pickett66 wrote in post #976562:

But that errors, any ideas? I'm not sure if I'm doing the REGEX correctly, could use some regex help.

First, I agree with Marnen that this should be done in the model but I disagree that the regexp is formed correctly on a very minor point; you don't need to add the '/' inside the quotes when building a new regexp object i.e. Regexp.new('some regexp') rather than Regexp.new('/ some regexp/').

Quite right. I was reading too fast and missed that.

So what I would do in the model is:

class User < AR::B   INVALID_EMAILS = %w(gmail.com hotmail.com)   def self.valid_email?(email)      reg = Regexp.new(INVALID_EMAILS*'|') # *'string' is an alias for .join('string') use whichever you preffer      matches = reg.match(email)      return matches == 0   end end

Better yet, do this as a custom validator method.

Then in the controller you can do

def some_action   if User.valid_email?(params[:email])     #do stuff   else     #do other stuff   end end

This has the added benefits that you can use this same validation anywhere in your code and easily add additional conditions to your validation in a single place.

Right. And if you do this as a custom validator, then it will run as part of Rails' validation routines without even needing that much controller code.

-T

Best,