I have the following validation:
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..40 }, :format => { :with => pass_regex }, :unless => :nopass?
Then, when I try to update without password (nopass? is true) the following errors appear:
There were problems with the following fields:
Password is too short (minimum is 6 characters)
Password is invalid
Notice that the :unless works on :presence and :confirmation but not in :lenght or :format.
How could I fix this?
I've had some strange issues with the :confirmation flag as well, which I never figured out, but that's how I solved the problem in my Rails 3.0.x app:
attr_accessor :password_confirmation
validates :password, :presence => true, :length => {:within => PASSWORD_MIN_LENGTH..PASSWORD_MAX_LENGTH}
validate :password_is_confirmed
def password_is_confirmed
if password_changed? # don't trigger that validation every time we save/update attributes
errors.add(:password_confirmation, "can't be blank") if password_confirmation.blank?
errors.add(:password_confirmation, "doesn't match first password") if password != password_confirmation
end
end
I realise this is not an explanation why your code isn't working, but if you're looking for a quick temporary fix - I hope this will help.
You might use conditional validations
class Person < ActiveRecord::Base
validates :surname, :presence => true, :if => "name.nil?"
end
Related
Here's what I expected to be a perfectly straightforward question, but I can't find a definitive answer in the Guides or elsewhere.
I have two attributes on an ActiveRecord. I want exactly one to be present and the other to be nil or a blank string.
How do I do the equivalent of :presence => false? I want to make sure the value is nil.
validates :first_attribute, :presence => true, :if => "second_attribute.blank?"
validates :second_attribute, :presence => true, :if => "first_attribute.blank?"
# The two lines below fail because 'false' is an invalid option
validates :first_attribute, :presence => false, :if => "!second_attribute.blank?"
validates :second_attribute, :presence => false, :if => "!first_attribute.blank?"
Or perhaps there's a more elegant way to do this...
I'm running Rails 3.0.9
For allowing an object to be valid if and only if a specific attribute is nil, you can use "inclusion" rather than creating your own method.
validates :name, inclusion: { in: [nil] }
This is for Rails 3. The Rails 4 solution is much more elegant:
validates :name, absence: true
class NoPresenceValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors[attribute] << (options[:message] || 'must be blank') unless record.send(attribute).blank?
end
end
validates :first_attribute, :presence => true, :if => "second_attribute.blank?"
validates :second_attribute, :presence => true, :if => "first_attribute.blank?"
validates :first_attribute, :no_presence => true, :if => "!second_attribute.blank?"
validates :second_attribute, :no_presence => true, :if => "!first_attribute.blank?"
use custom validation.
validate :validate_method
# validate if which one required other should be blank
def validate_method
errors.add(:field, :blank) if condition
end
It looks like :length => { :is => 0 } works for what I need.
validates :first_attribute, :length => {:is => 0 }, :unless => "second_attribute.blank?"
Try:
validates :first_attribute, :presence => {:if => second_attribute.blank?}
validates :second_attribute, :presence => {:if => (first_attribute.blank? && second_attribute.blank? )}
Hope that help .
Ive got the following problem. I have a model called user which has a column named activated. Im trying to update that value whith the method activated?, but it gives me the error: Validation failed: Password can't be blank, Password is too short (minimum is 6 characters) Which doesnt make sense to me, because im not touching the password field! I just want to update the activated column. Im putting here the code I think its relevant, but if you think you need more just ask :)
Thank you very much in advance!
Model:
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation, :activated
has_many :sucu_votes
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => {:with => email_regex},
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:length => { :within => 6..15 },
:confirmation => true
before_save :encrypt_password
def activated?
self.update_attributes!(:activated => true)
return self.activated
end
Controller from which the method activated? is called
def activate
if request.get?
user=User.find_by_id(params[:id])
if user.activated?
flash[:notice]="Your account has been activated"
#redirect_to :controller => 'sessions', :action => 'new'
else
flash[:error]="We couldnt activate the account"
redirect_to :controller => 'sessions', :action => 'new'
end
end
end
Two things, first the ruby convention is to use predicate methods to return true or false only and not to do anything more like update a record. That is not causing your problem but is a deviation from what other programmers would expect. Secondly, instead of calling update_attributes try just calling:
update_attribute(:activated, true)
This should skip the rest of the callbacks for the record
I'm trying to set my program so that the password only is validated if it is changed (so a user can edit other information without having to put in their password).
I am currently getting an error that says
NoMethodError in UsersController#create, undefined method `password_changed?' for #<User:0x00000100d1d7a0>
when I try to log in.
Here is my validation code in user.rb:
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence =>true, :confirmation => true, :length => { :within => 6..40 }, :if=>:password_changed?
Here is my create method in users_controller.rb:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
#title = "Sign up"
render 'new'
end
end
Thank you!
Replace with:
:if => lambda {|user| user.password_changed? }
I'd do two different validations:
validates :password, :presence =>true, :confirmation => true, :length => { :within => 6..40 }, :on => :create
validates :password, :confirmation => true, :length => { :within => 6..40 }, :on => :update, :unless => lambda{ |user| user.password.blank? }
I encountered this same problem and after reading this post I implemented the code suggested by apneadiving in his answer but with a slight modification:
I used two different validations, one for create:
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..128 }, :on => :create
and then I used this one for update:
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..128 }, :on => :update, :unless => lambda{ |user| user.password.to_s.empty? }
Originally, I Implemented exactly what apneadiving suggested, but I realized that on updates to the user it wasn't actually validating the presence of a string. As in, it was allowing a user to set their password to " " (A string of whitespace). This is due to the fact that " ".blank? == true, and so if you have it set to validate like this:
:unless => lambda { |user| user.password.blank? }
Then it won't run the validation if a string full of whitespace is submitted by the user is submitted because it reads the string as being blank. This essentially invalidates the effect of validating for presence on the update. The reason I did password.to_s.empty? instead of simply password.empty? is to prevent errors if someone calls update_attributes on the user model and doesn't pass in anything into the password, field, then the password will be nil, and since the ruby nil class doesn't have an empty? method, it will throw an error. Calling .to_s on nil, however will convert it to an empty string, which will return true on a successive .empty? call (thus the validation won't run). So after some trials and tribulation I found that this was the best way to do it.
Ended up here googling this error message, and using
#account.encrypted_password_changed?
in my case yielded what I wanted.
The change to look for, in Rails 4 at least, is password_digest.
#account.password = "my new password"
#account.changes # => {"password_digest"=>["$2a$10$nR./uTAmcO0CmUSd5xOP2OMf8n7/vXuMD6EAgvCIsnoJDMpOzYzsa", "$2a$10$pVM18wPMzkyH5zQBvcf6ruJry22Yn8w7BrJ4U78o08eU/GMIqQUBW"]}
#account.password_digest_changed? # => true
I am using Ruby on Rails 3.0.9 and I am trying to validate a nested model in a specific context just for the email attribute uniqueness.
In my controller I have:
#user.valid? :uniqueness_context
In my nested model I have:
validates :email,
:format => {
:with => EMAIL_REGEX
},
:uniqueness => {
:on => :uniqueness_context # Here it doesn't work
},
:presence => true
What is wrong? How can I make the above validation code to work?
Notice: if in the model I use the following:
validates :email,
:format => {
:with => EMAIL_REGEX
},
:uniqueness => true,
:presence => true
all works as expected.
In order to solve the issue I have tried also to use the following in the model:
validates :email,
:format => {
:with => EMAIL_REGEX
},
:presence => true
validates_uniqueness_of :email, :on => :uniqueness_context
but it still doesn't work.
I ran into the same problem. Seems that Rails currently does not support custom validation contexts. :if will do the job for you.
Sorry, I spaced it for a minute because I didn't realize you could create a custom context.
Looking at the source, it doesn't appear that the UniquenessValidator supports the :on context option.
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/validations/uniqueness.rb
So I have interesting password validation requirements:
When a user signs up, I want them to have to type in password and confirm and be between 6..40 (GOT THIS WORKING 100%)
When a user updates their profile, the same validation rules apply (GOT THIS WORKING 100%)
When an admin adds a user, they only have to enter the password once and it should be validated (NOT WORKIG)
When an admin edits a user and the password field is blank, it shouldn't update the password, if they type something, it should be validated. (PARTIAL WORKING)
validates :password, :presence => true,
:confirmation => true,
:length => {:within => 6..40},
:unless => :force_submit
The only cases I can't cover are when an admin adds a user, it is not validated and when an admin edits a user (and types in a password) it is not validated.
the :force_submit is passed in from the admin form, so the password isn't validated. (So the case of an updating empty password works)
Any ideas/magic?
Building slightly on the accepted answer, here's the code that I used in a Rails project at work. (Note: We're using devise to handle user authentication, and devise_invitable to create new users.)
PASSWORD_FORMAT = /\A
(?=.{8,}) # Must contain 8 or more characters
(?=.*\d) # Must contain a digit
(?=.*[a-z]) # Must contain a lower case character
(?=.*[A-Z]) # Must contain an upper case character
(?=.*[[:^alnum:]]) # Must contain a symbol
/x
validates :password,
presence: true,
length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT },
confirmation: true,
on: :create
validates :password,
allow_nil: true,
length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT },
confirmation: true,
on: :update
The below seem to meet my requirements...I am actually now requiring a confirmation for all users.. (It makes the view cleaner). But on an update I am allowing blanks.
validates :password, :presence => true,
:confirmation => true,
:length => {:within => 6..40},
:on => :create
validates :password, :confirmation => true,
:length => {:within => 6..40},
:allow_blank => true,
:on => :update
this works for blank password on update action:
validates :password, :presence => true, :on => :update,
:if => lambda{ !password.nil? }
validates :password,
:confirmation => true,
:length => { :minimum => 6},
:if => lambda{ new_record? || !password.nil? }
yet another variant
validates_presence_of :password_digest
validates_length_of :password, minimum: 6, if: Proc.new { |user| user.password.present? }