Validation of fields from some box on the view - Rails - ruby-on-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.

Related

Multi-step ActiveRecord's Model validation

Consider a User model with the following fields:
First name (required)
Last name (required)
Email (required)
Password (required)
Phone (required, size: 10 digits)
Address (required)
And a multi-step signup form with the following steps:
1st step with fields First Name, Last Name, and Email
2nd step with Password, Phone and Address.
How would you create a solution to validate the input in each step?
The standard ActiveRecord's way doesn't works, since it validates all fields at once.
I've created a solution for this problem but it turned out in a complicated code, so I'm looking for alternatives.
Personally I would let the model manage it's own validation and move the logic for managing validations for each step to that.
Now, this is probably not the most elegant way to do it but its effective and doesn't clutter the code too much.
Add a step transient attribute to the model.
attr_accessor :step
Add the following method to the model to check if on right step:
def on_step(step_number)
step == step_number or step.nil?
end
The reason for step.nil? - this has the advantage that if you want to use validation on this model without using steps simply don't assign a value for step on your model and the method will allows return true enabling the validation to always be carried out.
Change validations to process only if on right step or to bypass if not using steps
validates :first_name, if: "on_step 1", presence: true
validates :last_name, if: "on_step 1", presence:true
validates :email, if: "on_step 1", presence:true
validates :password, if: "on_step 2", presence:true
validates :phone, if: "on_step 2", format:{ with: TEL_REGEX }, allow_blank: false
validates :address, if: "on_step 2", presence:true
Of course don't forget to set the current step for the model, for example by hard-coding it in a hidden field of the form (if rendering separate forms for each step) and change your params to receive it.

Rails Conditional Validations

I am working on a project and need some help on where to begin. I have three pages
Update User
Create User
Admin User Password Change (like a Hard Reset Password for but only the admin can reset the user's password)
Change Password
On Create User first name, last name, username, password, and password confirmation are mandatory.
On Update User just first name, last name and username are mandatory.
On Admin User Password Change and Change Password, just password and password confirmation are mandatory.
How would you go about doing this? I don't think this is possible through models using validates_presence_of with an if because there are too many scenarios. Any help or guidance would be appreciated. Also, I am pretty new to Rails if you can't already tell.
You can pass conditionals to your validations:
validates :password, :confirmation => true, :presence => true
validates :first_name, :last_name, :username, :presence => true
validate :admin_user_password_change?
Of course you'd have to define what the admin_user_password_change? method would be to determine if it is an admin user changing a password.
UPDATE
The admin_user_password_change? method might be something like:
def admin_user_password_change?
unless self.admin? && self.password.present? && self.password_confirmation.present?
self.errors.add(:admin_password_change, "password and password_confirmation are required.")
end
end
As for How would it communicate with the controller?, it wouldn't directly. But if any of the conditions in the method are false (e.g. self.admin? && self.password.present? && self.password_confirmation.present?), an error will be added to the instance of User and the instance won't save in the controller.
Setting some fields to new values doesn't unset other fields; just because you're only updating some fields in one action doesn't mean the other fields will be unset, so long as they start in a consistent state.
Just add your validations. It will work fine.
You can tell to your validation work only on certain cenarios only using:
The create:
validates :first_name, :last_name, :username, presence: true, on: :create
The update:
validates :password, presence: true, on: :update
Take a look at on.
For validation based on context take a look at Context Validations

Check if an input box exists in rails

I have to check if confirm_password input box exists in form.If it exists,
I need to do this:
validates :password,:confirmation=>true
else
set confirmation to false.
Detail explanation for the problem:
I'm using rails client_side_validation gem which converts models validation into javascript form validation.
There is a little problem with this as login and sign up belongs to same table both of them have one Model. Now when I'm adding this in model for validation:
validates :password,:confirmation=>true
It will not let me to login as validation will become false as there is no confirm_password input box on login.It will only work on signup.
Assuming a model User add #user.is_signup = true to the signup action in users_controller. In your User model add attribute_accessor :is_signup and validates :confirm_password, :confirmation => true, :if => :is_signup.
In your signup form you could have a hidden field that gets passed in the form. If the attribute is present and returns true then you validate the presence of the password confirmation.
Signup form, somewhere inside the form tags:
<%= form.hidden_field :is_signup, true %>
Model:
attribute_accessor :confirm_password
attribute_accessor :is_signup
validates :confirm_password, :presence => true, :if => :validate_confirm_password?
def validate_confirm_password?
is_signup
end

Multiple validation error issue while saving a model in rails 3

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.

preventing rails validation based on previous validation

I have a model with 2 validations on the 'name' attribute. It goes something like this:
validates :name, :uniqueness => true
validate do
errors.add(:name, "is dumb") if name_is_dumb?
end
I don't want the 2nd validation to run if the first validation fails (the name is not unique).
What's the best and cleanest way to do this?
According to the documentation:
Callbacks are generally run in the
order they are defined, with the
exception of callbacks defined as
methods on the model, which are called
last.
So the following snippet should work:
validates :name, :uniqueness => true
validate do
errors.add(:name, "is dumb") unless errors[:name].nil?
end

Resources