Multiple validation error issue while saving a model in rails 3 - ruby-on-rails

I am having an issue while saving a user object in the database. I have two fields in the model (email and password) which are not allowed to be null in the database itself. Plus I have added validation in the model like
validates_presence_of :email, :message => "must be provided"
validates_presence_of :password, :message => "must be provided"
Now when I try to save the model from the create method of the controller, it invalidates the data and renders the new action again. However I have multiple error messages for each field
Email can't be blank
Email must be provided
Password can't be blank
Password must be provided
I don't need multiple error messages for the same one. How can I eliminate this?

Looks like you are validating in two different places. You have to figure it out the places...
If you are doing two different validation for a field and want to display one error message on a field at a time, you can do the following,
validates_presence_of :email, :message => "must be provided"
validates_uniqueness_of :email, :message => "must be unique",
:if => lambda { |a| a.errors.on(:email).blank? }

Looks like you are rendering errors twice. Check all your views, they can also be inherited.

Related

add custom validation method in Ruby on Rails

I need create a method the custom validation called findUpperCaseLetter or similar
I have a attribute called password that belongs to the model called User
My method is somewhat similar to the following. The password attribute must have at least a uppercase letter
def findUpperCaseLetter(username)
username.each_char do |character|
return true if character=~/[[:upper:]]/
end
return false
end
I want add this validation to the User model
class User < ActiveRecord::Base
attr_accessible :user_name,:email, :password
validates_presence_of :user_name,:email, :password
validates_uniqueness_of :user_name,:email
????
end
I have already the following regular expreession
validates_format_of :password, :with => /^[a-z0-9_-]{6,30}$/i,
message: "The password format is invalid"
How I modify it for add the following
The password must have at least one uppercase letter
You don't need custom validation to do this, you can use regex to validate the format of password. Add this to your model
validates :password, format: { with: /^(?=.*[A-Z]).+$/, allow_blank: true }
In Rails, you can do this by using format validator, I have added allow_blank: true to make sure when the field is empty it only throws Can't be blank error message and not format validator error message.
The work of this regular expression is to allow the password to be saved in the database only if it contains at least one capital letter. I have created a permalink on rubular, click here http://rubular.com/r/mOpUwmELjD
Hope this helps!

Validation of fields from some box on the view - Rails

I have an User model. It has next fields:
attr_accessible :user_name, :first_name, :last_name, :email ....
There is a profile view for the User with 6 blocks. Each of them associated with the various fields. Box 1 - first_name and last_name, Box 2 - user_name and email, etc.
I need to validate all the fields (presence, format, etc). But validators must trigger only for those fields, that has came from a particular block (Box 1 or Box 2, for example).
If I write something like next:
validates :user_name, :presence => true
and I will not edit the block with the *user_name*, I will see the error "user Name can't be blank". I can't use *:allow_blank => true* or nil because it can't(!) be blank!
In two words: I must validate only those fields, that was past from the resquest.
What I can do to solve my problem? Thx
You can add if or unless option to skip of particular condition.
validates :user_name, :presence => true, :if => "first_name.blank? and last_name.blank?"
You can pull the specific fields out of your model and create a model for each block, then you add one_to_one relationships to your User model.

Rails validation problem

I've got a User model with three fields, :email, :display_name and :handle. Handle is created behind the scenes from the :display_name.
I'm using the following validations:
validates :display_name, :presence => :true, :uniqueness => { :message => "Sorry, another user has already chosen that name."}, :on => :update
validates :email, :presence => :true, :uniqueness => { :message => "An account with that email already exists." }
I use the handle as the to_param in the model. If the user fails the validation by submitting a :display_name that already exists, then tries to change it and resubmit the form, Rails seems to use the new handle as the validation for the email -- in other words, it assumes that the email doesn't belong to the current user and validation on the email then fails. At this point, Rails assumes that the changed display name/handle is the one to use for the look up and the update action can't complete at all, because it can't find the user based on the new handle.
Here's the update method:
def update
#user = User.find_by_handle(params[:id])
#handle = params[:user][:display_name]
#user.handle = #handle.parameterize
...
end
This problem doesn't happen when the validation first fails on a duplicate email, so I'm assuming it's something about the way I've written the update method -- maybe I should try setting the handle in the model?
maybe I should try setting the handle in the model?
^ This.
The controller isn't the place to do something like this. If it's model logic that's happening behind the scenes, beyond the user's control, why put it in controller code?
Do it instead in a before_save filter, which is guaranteed to run only after the chosen display name is determined to be available and the record is deemed valid. In this way the handle won't be changed on the cached record until it is actually committed to the db, eliminating the problem of the incorrectly generated URL.
before_save :generate_handle
...
def generate_handle
self.handle = display_name.parameterize
end

Rails 2.3 uniqueness validation - how can I capture the value causing the error

I'm trying to capture the value that's throwing a uniqueness error (or for that matter, any other type of built-in validation) to display it in the :message option. Here's what I tried (didn't work)
# inside the model
validate_uniqueness_of :name, :message => "#{name} has already been taken" # also tried using #{:name}
I could use a custom validation, but this beats the point of using something that's already integrated into AR. Any thoughts? thanks.
Try this interpolation technique:
validate_uniqueness_of :name, :message => "%{value} has already been taken"
The RailsGuide for Active Record Validations and Callbacks shows an example where %{value} is interpolated in a custom error message:
:message => "%{value} is not a valid size"
I looked at the validates_each documentation and can see the validate block is passed three properties: |record, attr, value|. All three can be accessed with %{model}, %{attribute} and %{value}.
While this is limited, since it only gives you access to three properties, thankfully that is all you need.
Try self.name
validates_uniqueness_of :name, :message => "#{self.name} has already been taken" # also tried using #{:name}
Also validate_uniqueness_of is wrong it should be validates_uniqueness_of
If this not works use validate method and comment line validates_uniqueness_of
def validate
name= User.find_by_name(self.name) #Assuming User is your Model Name
unless name.blank?
self.errors.add :base, "#{self.name} has already been taken"
end
end

How to test custom messages thrown back by a models validation in Rails

I have this validation in my user model.
validates_uniqueness_of :email, :case_sensitive => false,
:message => "Some funky message that ive cleverly written"
In my tests I want to ensure that when a user enters a dupe email address that my message definately gets shown but without having to duplicate the error string from above in my test. I dont like that because im sure the message will change as i start thinking about copy. Does rails store these error messages - something which i can call in my tests?
Ive done a general test of
assert #error_messages[:taken] , user.errors.on(:email)
but that would pass on any of the other email related errors ive set validations up to catch i.e. incorrect formating, blank etc.
I made a quick test, and it looks like the error messages are sorted in the order you wrote your validation statements in your model class (top-down).
That means, you can find the error message for the first validation on an attribute at the first place in the errors array:
user.errors.on(:email)[0]
So, if your user model class contains something like this:
validates_presence_of :email
validates_uniqueness_of :email, :case_sensitive => false, :message => "Some funky message that ive cleverly written"
validates_length_of :email
...you'll find your 'funky message' at user.errors.on(:email)[1], but only if at least validates_presence_of triggers an error, too.
Concerning your specific problem:
The only way I could think of to not repeat your error message in the test, is to define a constant in your user model and use this instead of directly typing a message for that validation:
EMAIL_UNIQUENESS_ERROR_MESSAGE = "Some funky message that ive cleverly written"
...
validates_uniqueness_of :email, :case_sensitive => false, :message => EMAIL_UNIQUENESS_ERROR_MESSAGE
In your test, you could use this constant, too:
assert_equal User::EMAIL_UNIQUENESS_ERROR_MESSAGE, user.errors.on(:email)[1]
In rspec,
it "should validate uniqueness of email" do
existing_user = User.create!(:email => email)
new_user = User.create!(:email => existing_user.email)
new_user.should_not be_valid
new_user.errors.on(:email).should include("Some funky message that ive cleverly written")
end

Resources