rails email validation with name and email - ruby-on-rails

I want to write a validation for email filed .But some different way.
I will allow user to enter email in two format like "name 'email#example.com' " and simple 'email#example.com' .so basically i want to write a validation which will check that is valid email format in present in the value or not.
Just need a custom validation for check the valid email format is present in the input email value.
My model look like :
class Contact < ActiveRecord::Base
validates :email ,presence: true
validate :email_format
def email_format
??? what to write here ???
end
end
How can i write a validation for this.

You need to slightly modify the regular expression in your case.
validates :email, format: { with: /(\A([a-z]*\s*)*\<*([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\>*\Z)/i }
This will match the following formats.
soundar.rathinsamy#gmail.com
Soundar<soundar.rathinsamy#gmail.com>
Soundar <soundar.rathinsamy#gmail.com>
soundar<soundar.rathinsamy#gmail.com>
Soundar Rathinsamy<soundar.rathinsamy#gmail.com>
Soundar Rathinsamy <soundar.rathinsamy#gmail.com>
soundar rathinsamy <soundar.rathinsamy#gmail.com>
If you need some change continue editing this regular expression at rubular.com

validates :email, format: { with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
Taken from apidock.com: http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates

This code extracts from the email a string between "<" and ">" but if it doesn't find a match then it takes the last word in the email... in either case it then takes that string and tests for a valid email.
So it should work for "John john#example.com" and "John<john#example.com>"
def email_format
test_string = $1 if email =~ /\<([^\>]+)\>/
test_string = email.split(' ').last unless test_string
return if test_string =~ /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
errors.add(:email, "not a valid email")
end

Related

Rails/Phonelib: Why does my telephone number validator fail?

I am using PhoneLib (https://github.com/daddyz/phonelib) to validate my phone numbers.
I have a model Subscription with a column phone_number.
I'm testing this phone number: 3052612151.
I can see that Phonelib considers it to be a valid number:
> Phonelib.valid_for_country? "3052612151", :us
#=> true
However, when I use Phonelib's validator, my record is not considered to be valid.
class Subscription < ApplicationRecord
validates :email, presence: true
validates :phone_number, phone: { countries: :us }
> s = Subscription.create(phone_number: '3052612151', email: 'example#example.com')
> s.valid?
#=> false
> s.errors.full_messages
#=> ["Phone number is invalid"]
I've been scratching my head for over an hour. Can anyone see what I've done wrong? Why does Phonelib consider the number to be valid when calling #valid_for_country? but not when used as a validator?
The only thing I can think of is maybe you should set the default country in an initializer
# config/initializers/phonelib.rb
Phonelib.default_country = "US"
Then just use validates :phone_number, phone: true in your model.
Try using countries: [:us], the validator actually does a & operation and checks if the size is greater than 0, maybe it's expecting an array. https://github.com/daddyz/phonelib/blob/master/lib/validators/phone_validator.rb#L85
The validator actually checks 4 validations, it's a really bad design that all validations return the same error message, weird :S. https://github.com/daddyz/phonelib/blob/master/lib/validators/phone_validator.rb#L63

Regex on validates_format_of

I have a field in a form, and I need it to be registered only if its format equals one of the two regex I am using.
I have tried to use methods, the helper structure validates_format_of with Proc.new, but may not be using the correct syntax or the correct data type
private def format_field
errors.add(
:field, "The field does not have a valid format."
)unless[
/[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}\-?[0-9]{2}/,
/[0-9]{2}\.?[0-9]{3}\.?[0-9]{3}\/?[0-9]{4}\-?[0-9]{2}/
].include?(field.format)
end
A simple approach to this is the following:
FORMAT_REGEXES = [
/[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}\-?[0-9]{2}/,
/[0-9]{2}\.?[0-9]{3}\.?[0-9]{3}\/?[0-9]{4}\-?[0-9]{2}/
].freeze
def validate_format
return unless FORMAT_REGEXES.find { |regex| field.format =~ regex }
errors.add(:field, :invalid, message: 'The field does not have a valid format')
end

Rails 3 custom formatted validation errors?

With this model:
validates_presence_of :email, :message => "We need your email address"
as a rather contrived example. The error comes out as:
Email We need your email address
How can I provide the format myself?
I looked at the source code of ActiveModel::Errors#full_messages and it does this:
def full_messages
full_messages = []
each do |attribute, messages|
messages = Array.wrap(messages)
next if messages.empty?
if attribute == :base
messages.each {|m| full_messages << m }
else
attr_name = attribute.to_s.gsub('.', '_').humanize
attr_name = #base.class.human_attribute_name(attribute, :default => attr_name)
options = { :default => "%{attribute} %{message}", :attribute => attr_name }
messages.each do |m|
full_messages << I18n.t(:"errors.format", options.merge(:message => m))
end
end
end
full_messages
end
Notice the :default format string in the options? So I tried:
validates_presence_of :email, :message => "We need your email address", :default => "something"
But then the error message actually appears as:
Email something
So then I tried including the interpolation string %{message}, thus overriding the %{attribute} %{message} version Rails uses by default. This causes an Exception:
I18n::MissingInterpolationArgument in SubscriptionsController#create
missing interpolation argument in "%{message}" ({:model=>"Subscription", :attribute=>"Email", :value=>""} given
Yet if I use the interpolation string %{attribute}, it doesn't error, it just spits out the humanized attribute name twice.
Anyone got any experience with this? I could always have the attribute name first, but quite often we need some other string (marketing guys always make things more complicated!).
Errors on :base are not specific to any attribute, so the humanized attribute name is not appended to the message. This allows us to add error messages about email, but not attach them to the email attribute, and get the intended result:
class User < ActiveRecord::Base
validate :email_with_custom_message
...
private
def email_with_custom_message
errors.add(:base, "We need your email address") if
email.blank?
end
end
Using internationalization for this is probably your best bet. Take a look at
http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models
Particularly this section:
5.1.2 Error Message Interpolation
The translated model name, translated
attribute name, and value are always
available for interpolation.
So, for example, instead of the
default error message "can not be
blank" you could use the attribute
name like this : "Please fill in your
%{attribute}"

What is the best/easy way to validate an email address in Ruby?

What is the best/easy way to validate an email address in ruby (on the server side)?
You could look whether or not it matches a regexp like the one used in this Rails validator:
validates_format_of :email,:with => /\A[^#\s]+#([^#\s]+\.)+[^#\s]+\z/
But if you use Devise, simply do:
validates_format_of :email,:with => Devise::email_regexp
Source: http://lindsaar.net/2008/4/14/tip-4-detecting-a-valid-email-address
Edit 1:
useful website for tests: http://www.rubular.com/
In Ruby? The same way as in any language.
Send a confirmation email to the address with a link that the recipient has to click before the email address is considered fully validated.
There are any number of reasons why a perfectly formatted address may still be invalid (no actual user at that address, blocked by spam filters, and so on). The only way to know for sure is a successfully completed end-to-end transaction of some description.
validates :email, presence: true, format: /\w+#\w+\.{1}[a-zA-Z]{2,}/
checks that email field is not blank and that one or more characters are both preceding the '#' and following it
Added specificity, any 1 or more word characters before an the #and any 1 or more word character after and in between specifically 1 . and at least 2 letters after
I know that this is a old question but I was looking for a simple to way to do this. I came across a email_validator gem this is really simple to set up and use.
as a validator
validates :my_email_attribute, :email => true
Validation outside a model
EmailValidator.valid?('narf#example.com') # boolean
I hope that this help everyone.
Happy Codding
Shortcut Form:
validates :email, :format => /#/
Normal Form (Regex) :
validates :email, :format => { :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ }
Source: Validator Class
You can use
<%=email_field_tag 'to[]','' ,:placeholder=>"Type an email address",:pattern=>"^([\w+-.%]+#[\w-.]+\.[A-Za-z]{2,4},*[\W]*)+$",:multiple => true%>
Since the main answer's blog site was down, here is the snippet of code from that site via nice cacher or gist:
# http://my.rails-royce.org/2010/07/21/email-validation-in-ruby-on-rails-without-regexp/
class EmailValidator < ActiveModel::EachValidator
# Domain must be present and have two or more parts.
def validate_each(record, attribute, value)
address = Mail::Address.new value
record.errors[attribute] << (options[:message] || 'is invalid') unless (address.address == value && address.domain && address.__send__(:tree).domain.dot_atom_text.elements.size > 1 rescue false)
end
end
You can take reference from https://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_format_of
validates_format_of :email, with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
If you are using Rails/Devise - addition to #apneadiving`s answer -
validates_format_of :email,:with => Devise::email_regexp
Devise::email_regexp is taken from config/initializers/devise.rb
config.email_regexp = /\A[^#\s]+#([^#\s]+\.)+[^#\s]+\z/
Send a confirmation mail , and I will usualy use this validator ... D.R.Y.
# lib/email_validator.rb
class EmailValidator < ActiveModel::EachValidator
EmailAddress = begin
qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
'\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
quoted_pair = '\\x5c[\\x00-\\x7f]'
domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
domain_ref = atom
sub_domain = "(?:#{domain_ref}|#{domain_literal})"
word = "(?:#{atom}|#{quoted_string})"
domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
local_part = "#{word}(?:\\x2e#{word})*"
addr_spec = "#{local_part}\\x40#{domain}"
pattern = /\A#{addr_spec}\z/
end
def validate_each(record, attribute, value)
unless value =~ EmailAddress
record.errors[attribute] << (options[:message] || "is not valid")
end
end
end
in your model
validates :email , :email => true
or
validates :email, :presence => true,
:length => {:minimum => 3, :maximum => 254},
:uniqueness => true,
:email => true

How do you validate the presence of one field from many

I'm answering my own questions - just putting this up here for google-fu in case it helps someone else. This code allows you to validate the presence of one field in a list. See comments in code for usage. Just paste this into lib/custom_validations.rb and add require 'custom_validations' to your environment.rb
#good post on how to do stuff like this http://www.marklunds.com/articles/one/312
module ActiveRecord
module Validations
module ClassMethods
# Use to check for this, that or those was entered... example:
# :validates_presence_of_at_least_one_field :last_name, :company_name - would require either last_name or company_name to be filled in
# also works with arrays
# :validates_presence_of_at_least_one_field :email, [:name, :address, :city, :state] - would require email or a mailing type address
def validates_presence_of_at_least_one_field(*attr_names)
msg = attr_names.collect {|a| a.is_a?(Array) ? " ( #{a.join(", ")} ) " : a.to_s}.join(", ") +
"can't all be blank. At least one field (set) must be filled in."
configuration = {
:on => :save,
:message => msg }
configuration.update(attr_names.extract_options!)
send(validation_method(configuration[:on]), configuration) do |record|
found = false
attr_names.each do |a|
a = [a] unless a.is_a?(Array)
found = true
a.each do |attr|
value = record.respond_to?(attr.to_s) ? record.send(attr.to_s) : record[attr.to_s]
found = !value.blank?
end
break if found
end
record.errors.add_to_base(configuration[:message]) unless found
end
end
end
end
end
This works for me in Rails 3, although I'm only validating whether one or the other field is present:
validates :last_name, :presence => {unless => Proc.new { |a| a.company_name.present? }, :message => "You must enter a last name, company name, or both"}
That will only validate presence of last_name if company name is blank. You only need the one because both will be blank in the error condition, so to have a validator on company_name as well is redundant. The only annoying thing is that it spits out the column name before the message, and I used the answer from this question regarding Humanized Attributes to get around it (just setting the last_name humanized attribute to ""

Resources