Rails, Alphanumeric validation in the controller - ruby-on-rails

In my app I let users select a username, just like the twitter signup page: https://twitter.com/signup
When the user starts typing a username, I want in real-time to let the user know if the username is available & valid.
The regex I've been using to validate the username is alphanumeric is:
/^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i
Given params[:username]
In the controller, how can I validate if the username is alphanumeric or not. Note, I'm not saving the record here just validation. so a model validation wouldn't work.
Ideas? Thanks

You'd still want to use model validations.
Something like this perhaps:
class User
validates :username, :format => { :with => /your regex/ }, :uniqueness => true
end
# then in some controller action or rack app
def test_username
user = User.new(:username => params[:username])
# Call user.valid? to trigger the validations, then test to see if there are
# any on username, which is all you're concerned about here.
#
# If there are errors, they'd be returned so you can use them in the view,
# if not, just return success or something.
#
if !user.valid? && user.errors[:username].any?
render :json => { :success => false, :errors => user.errors[:username] }
else
render :json => { :success => true }
end
end

r = /^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i
unless your_string.match(r).nil?
# validation succeeded
end

I think your regex is a little overly verbose. I'd actually try the following regex for the alphanumeric validation:
/\A[A-Z0-9]+\z/i

Related

Devise Login Validation: Include Current URL in Validation

I was wondering if there is a way to include checking the current URL during login with devise.
Say that I have a user model with field :url, and that along with :email and :password, you also check if the current url matches with the user's :url field.
I was thinking I should do this in devise's self.find_for_database_authentication method and I currently have this:
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login).downcase
where(conditions).where('$or' => [{:username => /^#{Regexp.escape(login)}$/i}, {:email => /^#{Regexp.escape(login)}$/i}]).first
else
where(conditions).first
end
end
but what should I add to it so that it checks the current URL?
Note: I am using mongoid
Thanks in advance!
You should simply add the url to the query, something like this:
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
login = conditions.delete(:login).downcase
url = conditions.delete(:url ).downcase
if login && url
where(conditions).where(
:url => {"$eq" => url},
'$or' => [
{:username => /^#{Regexp.escape(login)}$/i},
{:email => /^#{Regexp.escape(login)}$/i}
]
).first
else
where(conditions).first
end
end
Where the hash it is sort of an implicit "and"

sending error message in json using ruby on rails

I am validating input fields in ruby on rails. I checking whether user have entered or filled these fields or not. If lets say name field is not filled then send an error message to user with indication that name field is not filled. Same goes with other errors. How can I send this kind of message in json using ruby on rails.
Here is what I am doing right now.
this model
validates :email, :name, :company, :presence => true
validates_format_of :email, :with => /\A[a-z0-9!#\$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+\/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\z/
Here is how I am currently sending json data to client
#contacts = Contact.new(params[:contact])
if #contacts.save
render :json => { :error => 0, :success => 1 }
else
render :json => { :error => 1, :success => 0 }
end
The simplest way would be to send down a hash of the errors.
so:
render :json => { :errors => #contacts.errors.as_json }, :status => 420
note that :status => 420 is required to make things like jquery's $.ajax method call their error callback and you should never return a 200 status (the default) when there is an error.
You really should use http status codes to tell the user what is going on, so for invalid record there is
420 Invalid Record Record could not be saved
And then in your JSON return you could also have an error message that would return your active record / active model error messages in it to give them more information.

Ruby on Rails Change Order of Custom Model Validations

I have a form that has model validations which works properly in my local system however when i check it on live site the order of the model validations order gets changed although the code is same in both.
this is the block of code in model:
def validate
#email validation
if !email.blank?
#errors.add(:email,I18n.t(:ismissing))
#else
if email != email_confirmation
errors.add(:email,I18n.t(:ErrorMessageConfirmEmailNotmatch))
else
if email.length <=200 then
if email.match(/^[^#][\w.-]*#[\w.-]+[.][a-z]{2,4}$/i).nil?
errors.add(:email,I18n.t(:ErrorMessageInvalid))
else
if #new_record==true
if User.find(:all, :conditions => ['lower(email) = ?', email.downcase]).count>0
#errors.add(:email," ID already exists. Provide another Email ID")
errors.add(:email,I18n.t(:ErrorMessageAlreadyExists))
end
else
if #changed_attributes["email"]!=nil
if User.User.find(:all, :conditions => ['lower(email) = ?', email.downcase]).count>0
#errors.add(:email," ID already exists. Provide another Email ID")
errors.add(:email,I18n.t(:ErrorMessageAlreadyExists))
end
end
end
end
else
errors.add(:email, I18n.t(:ErroeMessageMustlessthen,:size=>200))
end
end
else
errors.add(:email,I18n.t(:ismissing))
end
#end : Email validation
if email_confirmation.blank?
errors.add(:email_confirmation,I18n.t(:ismissing))
end
#pasword validation
if #new_record==true
if password.blank?
errors.add(:password,I18n.t(:ismissing))
else
if password_confirmation != password
errors.add(:password,I18n.t(:ErrorMessageConfirmPasswordNotmatch))
end
if !password.nil?
if password.length < 4 || password.length > 50 then
errors.add(:password,I18n.t(:ErroeMessageShouldBetween,:from=>"4",:to=>"50"))
end
errors.add(:password,I18n.t(:ErrorMessageInvalidPassword)) if password.match('^[a-z0-9##*-_]*$').nil?
end
end
end
#end password validation
if #new_record==true
if password_confirmation.blank?
errors.add(:password_confirmation,I18n.t(:ismissing))
end
end
if dob.blank?
errors.add(:dob,I18n.t(:ErrorMessageInvalid))
else
begin
#dt = DateTime.strptime(dob, "%m/%d/%Y").to_date
if dob.year <= 1900 then
errors.add(:dob,I18n.t(:ErrorMessageInvalidYear))
end
if dob>=Date.today then
errors.add(:dob,I18n.t(:ErroeMessageInvalidBirthday))
end
rescue Exception => ex
#errors.add(:dob,'is Invalid (MM/DD/YYYY format)')
errors.add(:dob,I18n.t(:ErroeMessageInvalidBirthday))
end
end
end
and the controller calls the Validate method on registration.An urgent help is required If anybody has any suggestions or ideas .
Thanks in Advance
You can use rails default validations..I did for email and gave you the sample here..
validates :email,
:presence =>{ :message => I18n.t(:ismissing)},
:length => {:allow_blank => true, :maximum => 200, :message => I18n.t(:ErroeMessageMustlessthen,:size=>200)},
:format => {:allow_blank => true, :with => /^[^#][\w.-]*#[\w.-]+[.][a-z]{2,4}$/i, :message => I18n.t(:ErrorMess
:uniqueness => {:allow_blank => true, :message => I18n.t(:ErrorMessageAlreadyExists)},
:confirmation => {:message => I18n.t(:ErrorMessageConfirmEmailNotmatch)}
Likewise you can also do for other fields.
Not sure why these wouldn't be executing in order. Have you logged something to indicate that in production?
Rather than put everything in a big validate method, maybe split into several (probably a better practice in general), then call in the order you want.
eg.
before_save :validate_email, :validate_dob
def validate_email
...
end
def validate_dob
...
end

Rails Tutorial case sensitive not working

I am following Rails tutorial and after signing up for my site, I am trying to sign in. I recently noticed in my app that if I capitalize my email address, I get the invalid username/password message. I tested the regex on Rubular and it works with capitalization so that can't be it.
Maybe this deals with sessions?
email_regex = /\A[\w+\-.]+#[csupomona\d\-.]+[edu]+\z/i
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
Here's the code for sessions/create
def create
user = User.authenticate(params[:session][:email],
params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = "Sign in"
render 'new'
else
sign_in user
redirect_to root_path
end
end
This is nothing to do with validation.
It is to do with
How email addresses are stored in the database (assumedly some upper case, some lower case)
How the User.authenticate works (I assume it does a User.find_by_email)
Looking at the question, I've never actually had this be a problem.
But to solve it there are a couple of ways to go about this.
Store all emails lowercase, and make User.authenticate do the same
Ensure that User.authenticate is case insensitive.
But I've got a feeling that User.authenticate is coming from Devise or something similar. So 1. may be the best solution
class User
# all email writes get lowercased
def email=(value)
self[:email] = value && value.downcase
end
end
user = User.authenticate(params[:session][:email].try(:downcase), ...)
You're a little confused about what that regex is for. Let us have a look at this:
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
Where is the regex being used? It is being used for the :format so the regex is only used to see if an incoming email address looks like a valid email address and that has nothing to do with uniqueness. The :uniqueness parameter to validates specifies that case shouldn't be considered when ensuring that email addresses are unique. So you can't have two users whose email addresses differ only by case.
Nothing in the code you've shown talks about how email addresses are compared when you're trying to sign someone in and that's where you're have trouble. You'll have to update your User.authenticate class method to do a case insensitive search for the email address.

Authlogic, can't update user because of validation

I've got authlogic setup as such
acts_as_authentic do |config|
config.login_field = 'email'
config.merge_validates_length_of_email_field_options :in => 5..50
config.validates_length_of_password_field_options = {:on => :update, :minimum => 4 }
config.validates_length_of_password_confirmation_field_options = {:on => :update, :minimum => 4}
end
I can't update user attributes because the password and password_confirmation try to get validated on save and they are nil. Is there any way to turn validations off temporarily, or a better solution?
Here's how it works for me:
Add a condition to your validate statements like this:
config.validates_length_of_password_field_options = {:on => :update, :minimum => 4, :if => :should_validate? }
Then add a custom should_validate? function to your user model. For example you could do
attr_accessor :updating_password
def should_validate?
updating_password or new_record?
end
This way you can explicitly set user.updating_password = true in your controller anytime you want the password to be validated and leave it as it is if you don't want any validation.
(This is my first answer, so I hope it's helpful for you. Otherwise don't hesitate to correct me.)

Resources