Skip to content

Instantly share code, notes, and snippets.

@ibanez270dx
Created June 19, 2016 09:34
Show Gist options
  • Save ibanez270dx/bdcc36927e1e04c3cc4169aa9d7b24ef to your computer and use it in GitHub Desktop.
Save ibanez270dx/bdcc36927e1e04c3cc4169aa9d7b24ef to your computer and use it in GitHub Desktop.
Snippets from my blog post "Better Conditional Validations in Rails"
class Person < ActiveRecord::Base
validates :surname, presence: true, if: "name.nil?"
end
user = User.new(name: 'Jeff', email: 'blah')
user.validated_fields = [:name, :email]
user.save # false
user.validated_fields = [:name]
user.save # true
user.fields_valid? [ :name, :email, :phone ] # true or false
def fields_valid?(fields)
# are there any existing errors?
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.
# run .valid? to repopulate @errors if need be. Otherwise, clear them.
(original_errors > 0) ? self.valid? : self.errors.clear
return validity
end
class User < ActiveRecord::Base
include ConditionalValidations
# ... your model code
end
module ConditionalValidations
attr_accessor :validated_fields
end
ActiveRecord::Base.extend ConditionalValidations
#pathway1_controller.rb
def create_user
user = User.new params[:user]
user.validated_fields = [ :name, :email ]
user.save
end
#pathway2_controller.rb
def create_user
user = User.new params[:user]
user.validated_fields = [ :name ]
user.save
end
class User < ActiveRecord::Base
include ConditionalValidations
conditionally_validate :name, presence: true
conditionally_validate :email, format: { with: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ }, length: { maximum: 100 }
end
def conditionally_validate(attribute, options=nil)
unless options.nil?
validates attribute, options.merge(if: "validated_fields.include?(:#{attribute})")
end
end
def conditionally_validate(attribute, options=nil)
unless options.nil?
unless options[:if].nil?
options[:if] = "#{options[:if]} && validated_fields.include?(:#{attribute})"
validates attribute, options
else
validates attribute, options.merge(if: "validated_fields.include?(:#{attribute})")
end
end
end
def conditionally_validate(attribute, options=nil)
unless options.nil?
unless options[:if].nil?
options[:if] = "#{options[:if]} && validated_fields.include?(:#{attribute})"
validates attribute, options
else
validates attribute, options.merge(if: "validated_fields.include?(:#{attribute})")
end
else
validate :"validate_#{attribute}", if: "validated_fields.include?(:#{attribute})"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment