RoR: Model validation question - ruby-on-rails

I have a basic ActiveRecord model in which i have two fields that i would like to validate. The requirement is that at least one of the fields must have a value. Both can have values, but at least one needs a value.
How do i express this with
validates_presence_of
statements? For example:
validates_presence_of :main_file
validates_presence_of :alt_file
i don't want an error to be generated if only one of them is empty, only if both are empty.

validates_presence_of :main_file, :if => Proc.new { |p| p.alt_file.blank? }
validates_presence_of :alt_file, :if => Proc.new { |p| p.main_file.blank? }

changing .nil? to .blank? does the trick!

Related

validate uniqueness of polymorphic association

I'm trying to implement a validation for a polymorphic association, where I only want it to trigger on a certain type. Which is user.
I'd want something like this:
validates :room_id, uniqueness: { scope: tokenable_id if tokenable type is User }
how do I go about doing this. The other type is Customer. Which I want to allow the opportunity to be several.
I think you can use Conditional Validation
Sometimes it will make sense to validate an object only when a given
predicate is satisfied. You can do that by using the :if and :unless
options, which can take a symbol, a string, a Proc or an Array. You
may use the :if option when you want to specify when the validation
should happen. If you want to specify when the validation should not
happen, then you may use the :unless option.
5.1 Using a Symbol with :if and :unless
You can associate the :if and :unless options with a symbol
corresponding to the name of a method that will get called right
before validation happens. This is the most commonly used option.
class Order < ActiveRecord::Base
validates :room_id, uniqueness: { scope: :tokenable_id }, if: :is_right_type?
# or maybe this will work
validates :room_id, uniqueness: { scope: :tokenable_id }, if: :user?
def is_right_type?
type == "user"
end
end

how to perform a complex validation check on related model prior to performing an action on a model?

I am building a simple Ruby on Rails app for problem management. I have a problem model as follows:
class Problem < ActiveRecord::Base
attr_accessible :active, :impact, :incident_number, :issue_description, :root_cause, :user_id, :problem_summary, :incident_priority, :timeline_enabled
attr_accessor :enable_timeline
validates :problem_summary, :length => { :in => 10..100 }
belongs_to :user
has_one :timeline
has_many :actionitems
end
which has a has_many belongs_to association with the model for actionitems:
class Actionitem < ActiveRecord::Base
attr_accessible :completion_date, :description, :initial_due_date, :notes, :problem_id, :revised_due_date, :status, :user_id
belongs_to :problem
end
I would like to be able to update the problem record and save it with some set of limited validations (I still need to add those). However, I would like to have a "Complete problem investigation" button that would trigger a method on the problem controller to set the :active attribute on the problem record to false. I would like to be able to run a different, more complete set of validations on the problem record prior to performing this action and also to validate that all actionitems (if any) that were associated with this problem record are in :status "completed".
The two questions that I have:
How do I perform a specific set of validations only on a given action?
How can I validate that related instances of Actionitem are in status "complete" prior to performing an action on Problem?
This task seems very complex to me. If you could please point me to what I need to utilize in order to be able to achieve this that would be greatly appreciated! (I read on validates :on => :save etc and accepts_nested_attributes_for but I am not sure how to put all of this together to achieve the behavior that I want).
Many thanks for all your help!
try this
validates_length_of :problem_summary, :in => 10..100, :if => :status_active?
def status_active?
self.active == true
end
see in details - validations & validates_length_of
U need to apply checking conditions on validations like
validate :xyz , length => {:in => 1..12}, :if => , :if => lambda {self.active == true }
this validation will only run when aCTIVE IS TRUE. similarly you can add more validation with checking

Rails - How to validate a field only if a another field has a certain value?

In my form I have a Select with three values: Apple, Banana and Cherry. If I choose Apple from the select I hide another Select- and a Text-field with some Javascript, because when Apple is chosen, there is no need to fill in these other two fields anymore.
So now I have a problem with validating my form when it's submitted.
I've found some similar problems for example in the case of
"Only validate a field if another is blank."
This problem was solved like this:
validates_presence_of :mobile_number, :unless => :home_phone?
So I've just tried the first thing which popped into my mind:
validates_presence_of :state, :granted_at, :if => :type != 1
But when I run it, I get this error:
undefined method `validate' for true:TrueClass
How can I conditionally perform a validation on a field based on whether or not another field has a particular value?
Because it is executable code you need to wrap it in a lambda or a Proc object like so:
validates_presence_of :state, :granted_at, :if => lambda { |o| o.type != 1 }
# alternatively:
..., :if => lambda { self.type != 1 }
..., :if => Proc.new { |o| o.type != 1 }
..., :if ->(o) { o.type != 1 }
You can use if flag and lambda:
validates_presence_of :state, :granted_at, :if => lambda {self.type != 1}
Or just create private method:
validates_presence_of :state, :granted_at, :if => :valid_type?
private
def valid_type?
type != 1
end
although the above mentioned ways are best practices but you can also make it simple like this:
validates_presence_of :state, :granted_at, :if => "type!=1"
Building on the previous answers, you can also use a shorter "arrow" syntax
validates :state, :granted_at, presence: true, if: ->(o) { o.type != 1 }

validations for certain actions in model

I am encountering a problem which I have never encountered before. I am working on code that was written by another programmer and it is kind of a mess.
Here is the problem. I have the following validations in the my model :
validates_presence_of :subscription_level,
:message => 'please make a selection'
validates_presence_of :shipping_first_name
validates_presence_of :shipping_last_name
validates_presence_of :shipping_address
validates_presence_of :shipping_city
validates_presence_of :shipping_state
validates_presence_of :shipping_postal_code
validates_presence_of :shipping_country
validates_presence_of :billing_first_name
validates_presence_of :billing_last_name
validates_presence_of :billing_address
validates_presence_of :billing_city
validates_presence_of :billing_state
validates_presence_of :billing_postal_code
validates_presence_of :billing_country
validates_presence_of :card_number
validates_numericality_of :card_number
validates_presence_of :card_expiration_month
validates_numericality_of :card_expiration_month
validates_presence_of :card_expiration_year
validates_numericality_of :card_expiration_year
validates_presence_of :card_cvv
validates_numericality_of :card_cvv
I have two actions for the controller in question. One is new and the other is redeem.
I want to perform all of these validations with the new action but want to skip most of them for redeem action.
The problem I am facing right now is that using valid? in the controller is also validating things which are not required for redeem action.
How can I get around this?
It's hacky, but I've had to resort to having an attribute flag that can enable/disable validations in certain states. (My specific example was a multi-page form, where we eventually want to validate all required fields for an object, but we only can validate data that has been submitted on previous pages)
Here's an example of how that might look:
class Whatever < ActiveRecord::Base
attr_accessor :enable_strict_validation
validates_presence_of :name # this always happens
validates_uniqueness_of :name, :if => :enable_strict_validation
end
Then somewhere else (eg your controller), you can do:
#whatever = Whatever.new(...)
#whatever.save # <= will only run the first validation
#whatever.enable_strict_validation = true
#whatever.save # <= will run both validations
Validations are not handled by the controller and as such are not action specific.
Validations can, however, be limited based on the type of update being made to the model. Update, Create, or Save.
Would it work for you to limit the validations only to new records?
validates_numericality_of :card_cvv, :on => :create
If not, you can write custom validators to handle returning true on conditions you specify (such as the controller action), but again it isn't really the "Rails Way".
The simplest example would be using the validate method
validate do
return true if my_action_is_redeem
self.card_cvv =~ /^\d*$/
end
For more info on validations see the docs
you can restrict the validate on the create (new) or on the update (redem operation is a update?).
your validation could be like this:
validates_presence_of :attribute1, :on => :update #so, only on redem method is validated)
You can choose when to validate, on this events: :create, :update, :save (both create or update)
More info on:
http://guides.rubyonrails.org/active_record_validations_callbacks.html#on

How to validate a field only if another has been filled out?

How would I validate a field only if another has been filled out In Ruby on Rails 2.3.5?
class Model < ActiveRecord::Base
validates_presence_of :address, :if => :city?
end
:address and :city are both attributes of Model.
validates_presence_of accepts an if attribute that take one of three things, according to the documentation: a string, a method, or a proc.
if - Specifies a method, proc or string to call to determine if the validation
should occur (e.g. :if => :allow_validation, or
:if => Proc.new { |user| user.signup_step > 2 }).
The method, proc or string should return or evaluate to a true or false value.
I ended up needing to use a proc, as I wanted to make sure that a certain parameter was filled out before validating:
validates_presence_of :bar, :if => Proc.new { |foo| !foo.age.blank? }

Resources