how to NOT update a field Ruby on Rails - ruby-on-rails

I'm a newbie in rails. how put a validated on password field. specified only on create and used an allow_blank method. but everytime i update it still creates a nil in the password field. any help?
validates :password, :presence => { :on => :create },
:confirmation => true,
:length => { :within => 8..40},
:allow_blank => true,

Try this:
validates :password, :presence => { :if => :new_record? },
:confirmation => true,
:length => { :within => 8..40 }

Related

Validates allow_blank of multiple columns

I validate Realty objects depending on their active_state, so if it's pending, multiple fields are allowed to be blank.
with_options :if => Proc.new { |a| a.active_state == 'pending'} do |realty|
realty.validates :street, :length => {:in => 1..100}, :allow_blank => true
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}, :allow_blank => true
realty.validates :city, :length => {:in => 1..50}, :allow_blank => true
realty.validates :description, :length => {:maximum => 8000}, :allow_blank => true
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}, :allow_blank => true
end
with_options :if => Proc.new { |a| a.active_state != 'pending'} do |realty|
realty.validates :street, :length => {:in => 1..100}
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
realty.validates :city, :length => {:in => 1..50}
realty.validates :description, :length => {:maximum => 8000}
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
end
The only difference are those :allow_blank => true options.
I want to make this code more dry, so my attempt would be to use the normal validations block once:
validates :street, :length => {:in => 1..100}
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
validates :city, :length => {:in => 1..50}
validates :description, :length => {:maximum => 8000}
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
and then simply call some function on all of those fields in case the state is pending:
with_options :if => Proc.new { |a| a.active_state == 'pending'} do |realty|
realty.allow_blank_of :street, :postalcode, :city, :description, :leasing_costs
end
Similar to all those validates_uniqueness_of :x, :y, :z methods.
I couldn't find a function to fit my need. How can I approach this?
It would be nice if the :allow_blank option took a proc, but I don't think it does. However, you can achieve the same result using the :if option since :allow_blank is essentially a way of saying "if the attribute is blank then don't run this validation requirement". So try this:
with_options :if => Proc.new { |a| a.active_state == 'pending' ? a.present? : true } do |realty|
realty.validates :street, :length => {:in => 1..100}
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
realty.validates :city, :length => {:in => 1..50}
realty.validates :description, :length => {:maximum => 8000}
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
end
The proc in this case is saying... if the active_state is 'pending' and the attribute is present then execute this validation. But if the active_state is not 'pending' then the attribute isn't allowed to be blank so always run the validation. I hope I got that logic right based on your needs.
From pdobb's answer
However, you can achieve the same result using the :if
option since :allow_blank is essentially a way of saying "if the
attribute is blank then don't run this validation requirement".
Based on pdobbs explanation what allow_blank => true actually does, I could narrow the validations down to:
validates :street, :length => {:in => 1..100}, :unless => :pending?
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}, :unless => :pending?
validates :city, :length => {:in => 1..50}, :unless => :pending?
validates :description, :length => {:maximum => 8000}, :unless => :pending?
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}, :unless => :pending?
def pending?
active_state == "pending"
end
So I simply skip all of those validations if the active_state is "pending".
Allot more DRY :)
I haven't ran this, but I think this may work
before_commit :build_callback_validator, :on => :create
def build_callback_validator
validates :street, :length => {:in => 1..100}
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
validates :city, :length => {:in => 1..50}
validates :description, :length => {:maximum => 8000}
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
if self.active_state != 'pending'
self.allow_blank_of :street, :postalcode, :city, :description, :leasing_costs
end
end

Don't show other validation messages without presence

Right now, I have a User model with a username field that's being validated by:
validates :username,
:presence => true,
:length => { :in => 3..60 },
:format => { :with => /^[a-zA-Z0-9\-_ ]+$/ }
How can I hide the :length and :format validation errors if :presence is not met?
Try :allow_blank => true in 2nd and 3rd validations.
I think you can do like this:
validates :username,
:presence => true,
:length => { :in => 3..60, :allow_nil => true },
:format => { :with => /^[a-zA-Z0-9\-_ ]+$/, :allow_nil => true }
It will not care about length and format validations when username is not set, but it will work fine with at least one character typed.

Rails put validation in a module mixin?

Some validations are repetitive in my models:
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
How would I put that in a mixin? I get this error if I just put 'em in a mixin
app/models/validations.rb:5: undefined method `validates' for Validations:Module (NoMethodError)
module Validations
extend ActiveSupport::Concern
included do
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
end
end
The validates macro must be evaluated in the context of the includer, not of the module (like you probably were doing).
Your module should look something like this:
module CommonValidations
extend ActiveSupport::Concern
included do
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
end
end
Then in your model:
class Post < ActiveRecord::Base
include CommonValidations
...
end
I'm using ActiveSupport::Concern here to make the code a little clearer.

How to use Rails validates only if not a new user

I have the following in my user.rb:
validates :fname, :length => { :minimum => 1, :maximum => 100 }
validates :lname, :length => { :minimum => 1, :maximum => 100 }
How can I update this validations to only apply to existing users? I ask as I want to allow a user to signup without having to enter a fname or lname.
Ideas?
validates :fname, :length => { :minimum => 1, :maximum => 100 }, :unless => :new_record?
validates :fname, :length => { :minimum => 1, :maximum => 100 }, :unless => :new_record?
You can also use :on => :update, to make the validation only apply when a record is updated (as opposed to :on => :create)

Numericality Validations, Catching nil Values on Comparisons

I have an object that contains a number range and a description [min_val, max_val, name].
I need to validate that min_val < max_val. However, if one of them is blank I get a nil comparison error, instead, I'd like to tell the user that a number is required.
Also, how can I change the error message for numericality?
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :less_than => :max_val}
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :greater_than => :min_val}
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }
You can use :message to specify a custom error message.
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validate do |record|
record.errors.add_to_base("The min_val should be less than max_val") if min_val.to_i >= max_val.to_i
end
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }

Resources