How to use with_options for conditional validation - ruby-on-rails

How can I use with_options for conditional validation ?
My code is
with_options if: (AppUser::User.creator=="is_admin") do |admin|
admin.validates :first_name, :presence => true
admin.validates :last_name, :presence => true
end
I have already set creator method in application controller.
before_action :set_global_user
def set_global_user
if current_admin
AppUser::User.creator= "is_admin"
elsif current_user
AppUser::User.creator= "is_user"
else
AppUser::User.creator=nil
end
end
but I am getting
undefined method `validate' for false:FalseClass
what is wrong with this code.

because
(AppUser::User.creator == "is_admin")`
does not return an object but it is a boolean.
Try this (inside your model):
class User < ActiveRecord::Base
with_options if: (AppUser::User.creator == "is_admin") do
validates :first_name, presence: true
validates :last_name, presence: true
end
end
P.S: I recommend the use of the devise gem to manage user types like this:
devise and multiple “user” models.

Related

How not to allow validation for a specific action in Rails 4

I have this password validation in my user.model.rb:
class User < ActiveRecord::Base
validates :password, presence: true, confirmation: true,
format: {:with => /^(?=.*[0-9])(?=.*[A-Z])(?=.*[&%$##*])[a-zA-Z0-9&%$##*]{8,}$/,
:multiline => true, :message => I18n.t('invalid_password')}
end
I want this validation to be called in each and every method but not in my update action.
I have a users_controller.rb that has a create and update action. I want it to check in the create action but not in the update action.
I also have a password_resets_controller.rb in which I want it to check in both create and update actions but not in users_controller update action. I am using the authlogic gem. Both controllers use the same model.
Please guide me on how to do this. Thanks in advance.
validates :password, :presence => {:on => :create}
OR
##here new_user is a method that you can create and use condionally
## or validates_presence_of :password, :if => :new_user?
validates_presence_of :password, :unless => :new_user?
def new_user?
//your code
end
OR Using with_options
class User < ActiveRecord::Base
has_many :roles
# Normal Validations
validates_presence_of :password
with_options :if => :customer? do |customer|
customer.validates_presence_of :password
end
def customer?
roles.any? { |role| role.name == "customer" }
end
end
Probably the most close answer can be:
class User < ActiveRecord::Base
validates :password, presence: true, if: :not_persisted?
def not_persisted?
!self.persisted?
end
end
This code will actually trigger the validation only if the object is not persisted (on create)

How do I use an if statement in Rails validation?

I'm trying to create a validation statement that validates an object if service_area is present UNLESS service_area_radius==0
Here's the statement I created, which doesn't work:
validates :service_area, :presence => true, unless: "service_area_radius==0"
http://railscasts.com/episodes/41-conditional-validations
Like this:
validates_presence_of :password, :if => :should_validate_password?
validates_presence_of :country
validates_presence_of :state, :if => :in_us?
attr_accessor :updating_password
def in_us?
country == 'US'
end
def should_validate_password?
updating_password || new_record?
end
validates :service_area,
presence: {message: "Area Radius is missing."}, if: :radius_found?
private
def radius_found?
service_area_radius > 0
end
The validation for service_area will be executed if radius_found? returns true.
radius_found? will return true when the service_area_radius(attribute) hold value > 0.
Adding a custom message with message: option, when the validation fails.

Overriding presence true in User model

I have the following in my models/user.rb:
validates :company, presence: true
validates :title, presence: true
I have a secondary view where I want to create a user but not require this user to enter a company and a title. How would I do that without modifying the main user.rb?
This is for Rails 3.2
You can do by declaring custom validations the way #BroiSatse has answered or when saving the user you can pass validate: false as argument, do this way
#user.save(:validate => false)
I usually do sth like:
class User < AR::Base
validates :company, :title, presence: true, if: :validate_company_and_title?
def validate_company_and_title?
#validate_company_and_title.nil? || #validate_company_and_title
end
def skip_company_and_title_validation!
#validate_company_and_title = false
end
end
Then in your controller create action for given view you can do:
#user.skip_company_and_title_validation!

rails ActiveRecord validation on specific controller and action

is it possible to run ActiveRecord validates on given controller and action.
For example I have user_controller and signup_controller
I need to run password required validation only on signup_controller#create action
You can run validations using an if conditional:
validates :email, presence: true, if: :validate_email?
Now you need to define this instance method (in your model):
def validate_email?
validate_email == 'true' || validate_email == true
end
This validate_email attribute could be a virtual attribute in your model:
attr_accessor :validate_email
And now, you can perform email validation depending on that virtual attribute. For example, in signup_controller#create you can do something like:
def create
...
#user.validate_email = true
#user.save
...
end
use validates :password, :if => :password_changed? in user.rb
if form in users_controller does not submit password field then you should be ok.
Just a tip for implementing #markets' answer
We can use
with_options if: :validate_email? do |z|
z.validates :email, presence: true
z.validates :name, presence: true
end
for multiple validations on our specific action.
Also, we use session to pass a variable which indicate params from this action will need some validations
Controller:
before_action :no_validate, only: [:first_action, :second_action, ..]
before_action :action_based_validation, only: [:first_action, :second_action, ..]
def first_action; end
def second_action; end
def update
..
#instance.validate = session[:validate]
..
if #instance.update(instance_params)
..
end
end
private
def no_validate
session[:validate] = nil
end
def action_based_validation
# action_name in first_action will = "first_action"
session[:validate] = action_name
end
Model
attr_accessor :validate
with_options if: "validate == 'first_action'" do |z|
z.validates :email, presence: true
..more validations..
end
with_options if: "validate == 'second_action'" do |z|
z.validates :name, presence: true
..more validations..
end
more details:
http://guides.rubyonrails.org/active_record_validations.html#conditional-validation

Validation based on role

Right so I have one user table with different users. I need to validate user tables on update prior to them moving onto the main site.
so far I've just done the following, is there a way I can block the validations depending on a role without doing a custom validation method, like with_options :on => :update
before_validation :check_role
if check_role = "developer" do |dev|
dev.validate :first_name, presence: true # this doesn't work btw...
end
def check_role
return self.role_type unless self.role_type == nil
end
I figure it out and this looks like the best way to do it:
class YourModel
with_options :if => lambda { |o| o.whatever == "whatever" } do |on_condition|
on_condition.validates_presence_of :address
on_condition.validates_presence_of :city
end
with_options :if => lambda { |o| o.condition_the_second == "whatever" } do |on_condition|
on_condition.validates_presence_of :foo
on_condition.validates_presence_of :bar
end
end
validates :first_name, presence: true, if: :developer?
def developer?
role == 'developer'
end
with_options :if => Proc.new {|user| user.role_type == 'developer'} do |developer|
developer.validates :first_name, :presence => true
end

Resources