Skip to content

Instantly share code, notes, and snippets.

Forked from ibanez270dx/ConditionalValidations.rb
Created February 22, 2013 21:38
Show Gist options
  • Save keenahn/5016749 to your computer and use it in GitHub Desktop.
Save keenahn/5016749 to your computer and use it in GitHub Desktop.
# At CoverHound, we use conditional validations all over the form. However, there is no proper way to do
# this in Rails. Instead, we can provide an array of attributes (validated_fields attribute)
# and ensure they are the only ones to get validated.
module ConditionalValidations
attr_accessor :validated_fields
def field_is_required?(field)
unless validated_fields.blank?
def conditionally_validate(attribute, options=nil)
unless options.nil?
# Passing options for built-in validators
unless options[:if].nil?
options[:if] = "#{options[:if]} && field_is_required?(:#{attribute})"
validates attribute, options
validates attribute, options.merge(if: "field_is_required?(:#{attribute})")
# Block validation
# will initiate a validator on attribute using a method called validate_#{attribute}
validate :"validate_#{attribute}", if: "field_is_required?(:#{attribute})"
def fields_valid?(fields)
# Note that when validations are run, class variable @errors changes. As such, we have
# to keep track of whether there were errors originally and repopulate them as necessary.
original_errors = self.errors.messages.count
mock = self.dup # duplicate the model in a non-persisted way.
mock.validated_fields = fields # ...tell model what fields to validate.
validity = mock.valid? # run validations and change @errors.
# If there were errors on the original model, run valid? so that it populates @errors.
# Otherwise, remove any errors left over from the mock run.
(original_errors > 0) ? self.valid? : self.errors.clear
return validity
ActiveRecord::Base.extend ConditionalValidations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment