In my Rails app college students with either #berkeley.edu or #uw.edu email addresses can register. I have the regex for validating both ready but since I need to check the email address the user enters to see which one it matches I think I need to create one regex, but I don't know how. Here are my two regex's:
berkeley_regex = /\A[\w+\-.]+#berkeley\.edu\z/i
uw_regex = /\A[\w+\-.]+#uw\.edu\z/i
And my validate:
validates :email, :presence => true, :uniqueness => true, :format => {:with => berkeley_regex}
Now, what would the regex to check against both but only match against one look like?
Can't you just validate against something like /\A[\w+\-.]+#(berkeley|uw)\.edu\z/i and be done with it? If you really need to later determine which it is, make a method that just checks the back part, or returns the match, or whatever...
First I think your regex should be changed from [\w+\-.] to [\w+\-\.]
The validation could be
validates :email, format: { with: "\A#{berkely_regex}|#{uw_regex}\z/i" }
but you'll need to remove the flags ( \A, \z, /i ) from the vartiables
Related
I'm trying to validate the format of a field in an ActiveRecord. I want this field to either be empty, or contain a sequence of digits only (it is containing an optional port number for a database connection). I'm currently trying this:
validates_format_of :port, with: /\A[0-9]*\Z/, message: 'Only numbers allowed'
but without luck. I've found that adding a required number by using for example {1, 6} sort of works, but makes the field mandatory.
Any advice?
Many thanks in advance,
Joseph.
If you're looking to validate so that only numbers are allowed, then you should be able to use this:
validates :port, :numericality => {:only_integer => true}
You may want to try to validate the numericality of the field, like so:
validates_numericality_of :port, :only_integer => true
:only_integer will ensure that the value entered for :port is an integer.
You can also just add allow_blank: true
You can use this syntax as well
validates numericality: :only_integer
I would like to have a list of email domains that are validated against to prevent from registering on my app.
10minutemail.com, yopmail.com, mail.com, mail.ru etc...
I have a list of domains in my user model like so:
BAD_DOMAINS = [/10minutemail.com/, /yopmail.com/, /mail/
I would like to add a User validates on the email field to add an error if the user is registering with one of these domains.
BAD_DOMAINS.each { |rule| return true if !domain.match(rule).nil? }
I have that regex working, but how do I add that as a validates? I tried this:
validates :email, :format => { : exclusion => BAD_DOMAINS,
:message => "%{value} no good." }
Thanks
You need to combine all of your separate regular expressions into a singular one, but you might find it's easier to do that if you have a list of strings instead of a list of regular expressions:
EXCLUSION_DOMAINS = %w[
example.com
test.com
asdf.com
]
EXCLUSION_REGEXP = Regexp.new('(?:' + EXCLUSION_DOMAINS.collect { |d| Regexp.escape(d) }.join('|') + ')$')
You'll want to ensure that things don't match this, so it's a little different to use:
validates :email,
:format => {
:with => VALID_EMAIL_REGEXP,
:without => EXCLUSION_REGEXP,
:message => "%{value} no good."
}
You should use some kind of valid email tester as well to be sure the address is plausible. It's expressed here as VALID_EMAIL_REGEXP which is some kind of email validator regular expression. Try and use an RFC compliant one if you do that.
I'm building an app where users can create url slugs for their profile. To make sure the slugs are valid I've added a validation in the User model for slugs:
validates :slug, :uniqueness => true, :format => { :with => /[a-z]+/ }, :allow_nil => true, :allow_blank => true
However, validation seems to pass, regardless of what format the slug string is, for example:
u.slug = 'jlskdf .jc oi/slkdjfie\*asdf&(*&*ss%&'
=> "jlskdf .jc oi/slkdjfie\\*asdf&(*&*ss%&"
u.save
=> true
Apparently it doesn't matter what I change the regex to either, everything passes. I've tried this format as well:
validates_format_of :slug, :with => /[a-z]+/
which gives the same results. Anyone have any ideas of what could be happening?
Your regular expression isn't anchored, so the pattern matches as long as it contains at least one letter a-z. Anything else is valid. Add \A and \z to the beginning and end to prevent matching any substring within the larger input.
:with => /\A[a-z]+\z/
I have validation on uniqueness and I want skipping certain value or values(for example 0000):
validates_uniqueness_of :gtin, :scope => [:user_id, :item_id]
I'm tried to use next construction, but she don't work:
validates_uniqueness_of :gtin, :scope => [:user_id, :item_id], :unless => Proc.new{|base_item| base_item.gtin == '0000'}
How I can skip certain value or values?
Thanks.
P.S. update!!!
did not see a manual migration, which change behaviour
using the :unless option is certainly the right way, but i think you get the whole object as proc argument so it should be
validates_uniqueness_of :gtin, :scope => [:user_id, :item_id], :unless => Proc.new{|obj| obj.gtin == '0000'}
Not sure if this is a gotcha or not. Is the value of gtin a string or an integer? It looks like what your doing should work, but if it's an integer you would want to change to:
validates :gtin, :uniqueness => {:scope => [:user_id, :item_id]}, :unless => Proc.new{|base_item| base_item.gtin == 0000}
I'm trying to do the same thing, and I think I know what's wrong. The problem is, the if or unless "base_item" object refers to the value you're checking the uniqueness for, not the prospective match object.
Maybe you really do mean to check the item you're validating (in which case I'm barking up the wrong tree), but it seems more natural in the uniqueness case to want to exclude certain matches. For instance, I have a field is_deleted, and I want to allow a uniqueness violation if the matching object has been deleted.
I can't find any way to reference the matching object that was found in the proc. You can accomplish this by making your own a custom validation function though. For instance, if you want to validate the uniqueness of 'name', you might try something like this:
validate :full_validation
def full_validation
matches = self.class.find_all_by_name(self.name).select {|match| match.id != self.id && match.is_deleted==false}
return (matches.size>0)
end
In Rails 3, is there a built in method for seeing if a string is a valid IP address?
If not, what is the easiest way to validate?
Just wanted to add that instead of writing your own pattern you can use the build in one Resolv::IPv4::Regex
require 'resolv'
validates :gateway, :presence => true, :uniqueness => true,
:format => { :with => Resolv::IPv4::Regex }
The Rails way to validate with ActiveRecord in Rails 3 is:
#ip_regex = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/
validates :gateway,
:presence => true,
:uniqueness => true,
:format => { :with => #ip_regex }
Good resource here: Wayback Archive - Email validation in Ruby On Rails 3 or Active model without regexp
You can also just call standard's library IPAddr.new that will parse subnets, IPV6 and other cool things: (IPAddr) and return nil if the format was wrong.
Just do:
valid = !(IPAddr.new('192.168.2.0/24') rescue nil).nil?
#=> true
valid = !(IPAddr.new('192.168.2.256') rescue nil).nil?
#=> false
You can use Resolv::IPv4::Regex as Jack mentioned below if you don't need to accept subnets.
If you need to accept it, activemodel-ipaddr_validator gem may help you. (disclaimer: I'm the author of the gem)
validates :your_attr, ipaddr: true
i dont know about RoR a lot, but if you dont find any built in method for validation of IP Address.
Try on this regular expression :
"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"
to validate the IP Address.
I recently used it in one module so had it on desktop.
You should use a Regular Expression
Here is one that does what you want:
/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.
([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/.match("#{#systemIP}")
You can also use Regexy::Web::IPv4 which can match ip addresses with port numbers too.