In my en.yml I have this:
en:
errors:
format: "%{message}"
messages:
blank: "%{attribute} can't be blank"
invalid: "%{attribute} is invalid"
too_short: "%{attribute} is too short"
too_long: "%{attribute} is too long"
wrong_length: "%{attribute} is the wrong length"
taken: "%{attribute}, {value}, is already taken"
And here's my User model so far:
validates_presence_of :username
validates_uniqueness_of :username
validates_length_of :username, :within => 4..15
validates_format_of :username, :with => /^\w+$/i
validates_presence_of :password
validates_length_of :password, :within => 6..20
When I test random data, all error messages work great, except for the validates_uniqueness_of, which returns the default 'has already been taken'
Thank you very much in advance.
shouldn't it be
taken: "%{attribute}, %{value}, is already taken"
with percent sign for value?
I didn't know you could access value, but it makes sense, otherwise that could be username.
I see that taken is the right key, but I still would try without {value} to see if it works.
At last or temporary fix I think you can pass a message in you model validation, something like this should work:
validates_uniqueness_of :username, :mesage => "#{self.username} is already taken"
but of course you loose a lot of benefits.
Related
I'm new to rails testing and have written a simple unit test to check my validations. I want to check if my sample data is valid and check the name and email field.
bill_test.rb
test "sample data is valid" do
assert Bill.new(name: bills(:one).name, email: bills(:one).email).valid?, 'Sample data is not valid.'
end
My model:
validates_presence_of :name
validates :name, :length => {:maximum => 30 }
validates_presence_of :email
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :if => :email?
after running "rake test:units"
1) Failure:
BillTest#test_sample_data_is_valid [/Users/martinbraun/Documents/Projekte/pay-ma-bill/test/models/bill_test.rb:10]:
Sample data is not valid.
My fixture:
one:
name: Hans
email: hans#gmail.com
I also get the failure when removing the validations so I guess the mistake lies in my actual assert. But I cannot see any error there.
Any ideas?
visit this page, it may be helpful for you.
My User model contains the following:
validates :password_digest, :presence => true, :message => "The password has to be 6 or more characters long"
def password=(password)
self.password_digest = BCrypt::Password.create(password) if password.length >= 6
end
The issue is that the message in the validates isn't working. I get a Unknown validator: 'MessageValidator' error. I assumed the way the presence validation worked was that it would just check if the password_digest was nil, which it would be had the password had a length less than 6. I want a solution that is elegant, like what I attempted. I have solved this one way, but I would really appreciate an understanding as to why what I'm trying isn't working, and is there a way to make it work.
What I got to work was:
validate do |user|
user.errors['password'] = "can't be less than 6 characters" if user.password_digest.nil?
end
This is due to how the validates method works. It assumes that you're looking for the MessageValidator when you specify :message as a key in the hash passed to validates.
This can be solved by reconstructing the query as follows:
validates :password_digest, :presence => { :message => "The password has to be 6 or more characters long" }
I know you can do this:
# config/locales/en.yml
en:
activerecord:
attributes:
user:
email: "E-mail address"
errors:
models:
user:
attributes:
email:
blank: "is required"
via https://stackoverflow.com/a/2859275/718050
Question 1
Is it possible to specify the message for blank across an entire model, or even sitewide, instead of going into every single attribute?
Question 2
Also, it seems that blank comes from :presence in the model, e.g.
validates :email, :presence => true
So if a :presence => true error translates to blank:, where can I find a list of these translations? How am I supposed to know what :unique => true turns into inside en.yml?
This list is here and here
as you can see you can redefine blank error like this:
en:
errors:
messages:
blank: "can't be blank"
I'm using devise as authentication engine in my app.
Is there any way to use custom messages when devise validation fails.
Devise provides me with the following message when the password is blank: Password can't be blank, but i need another message. How can i do it?
ActiveRecord en.yml is the answer I would suggest if you want to change the Validation Message for Devise
Here is how the en.yml should look like
en:
activerecord:
errors:
models:
user:
attributes:
email:
blank: "Please Specify an Email id"
taken: "Please use a different Email id"
invalid: "Please Specify a valid Email id"
password:
blank: "Please Specify a Password"
confirmation: "Password does not match"
password_confirmation:
blank: "Please Specify a Password Confirmation"
first_name:
blank: "Please Specify First Name"
last_name:
blank: "Please Specify Last Name"
pdf:
attributes:
name:
blank: "Please Specify name to PDF"
taken: "Please use different name for PDF"
attachment:
blank: "Please Upload a PDF Attachment"
data_element:
attributes:
name:
blank: "Please give Element a desired name"
taken: "Already Created Element with given name"
color:
blank: "Please assign a color to Element"
template:
attributes:
name:
blank: "Please Specify a Name"
taken: "Please use a different name"
I advice you to define this way instead of customizing devise validation module
Because if you follow the above approach, it would be possible that you would skip a validation a place or two
for Example I the remove the above devise validation module and then substitue your own in
User Model
then all the validation would work for but you would miss the validation in Change Password
There by resulting your to login even though the password was never supplied and never given
Keep a loop of that too
Cheer
Regards
Please refer to the URL below.
http://railscasts.com/episodes/210-customizing-devise?view=asciicast
If the user is signing in, you can edit all the error messages in devise.en.yml under config/locales.
If you're signing up, Devise provides its own validations out of the box without any customizing. If you want to customize it, you can edit the User model.
Find devise :validatable and remove the :validatable option. After which, you should be able to use the usual rails validations. Note that this will cause you to have to do all the validations yourself.
validates_presence_of :password, :message=>"Your custom error message!"
Some usual validations:
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
Not a complete answer, but this sounds like it should be solvable with I18n, either with the devise-internal keys, or by overriding active record's validation error messages for your user model.
Here's a similar question: Devise attributes for i18n?
You can customize your devise messages from config/locales/devise.en.yml but if you want to change to validation message then delete :validatable from Model. Then you can change a validation message like before.
For example:
validates_uniqueness_of :email, :case_sensitive => false, :allow_blank => true, :if => :email_changed?
validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed?
validates_presence_of :password, :on=>:create
validates_confirmation_of :password, :on=>:create
validates_length_of :password, :within => Devise.password_length, :allow_blank => true
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