Skip to content

Instantly share code, notes, and snippets.

@coreyhaines
Created August 9, 2012 15:52
Show Gist options
  • Save coreyhaines/3305349 to your computer and use it in GitHub Desktop.
Save coreyhaines/3305349 to your computer and use it in GitHub Desktop.
Thoughts on ActiveModel::Validator as a validation service
# I love the helpers, they help to make the intention clear.
# I want to be able to do this. That is, using the validation helpers inside a validator object,
# rather than having to do manual validation.
class EmployeeValidator < ActiveModel::Validator
def validate(record)
record.validates_presence_of :email
end
end
# After some reading, I realize I can do this
class EmployeeValidator < ActiveModel::Validator
def setup(employee_class)
user_class.validates_presence_of :email
end
def validate(record)
end
end
# This provides the ability to use the helpers from a validator object.
# Now, I'm working on a way to bypass the validations from examples
# that aren't concerned with the validity of an object, such scope examples.
# Unfortunately, the setup method is called once when validates_with is called
# since ActiveRecord caches the validation objects. So, it has already been called
# and configured with the validation before a non-validation-oriented example
# can use it. So, no over-riding.
# Looking at the way validation helpers work, they all are backed by a subclass of
# Validator (or EachValidator), so you should be able to instantiate one and use it.
class EmployeeValidator < ActiveModel::Validator
def validate(record)
ActiveModel::Validations::PresenceValidator.new(attributes: [:first_name]).validate record
end
end
# This works for doing the validation.
# Yes, this is ugly, but we can wrap it in a helper, perhaps even having Active Record models
# expose the helpers on an instance level.
# However, when our example runs that wants to bypass them, it keeps using the old version.
# I want to be able to do this at the top of my validation-less example.
class EmployeeValidator < ActiveModel::Validator
def validate(record); end
end
# But, because the instance of the validator is cached when validates_with EmployeeValidator is
# called, my over-ride does not cut in. Boo!
# ActiveModel::Validations uses hooks to call the validations.
# Is there a way to disable the hook for a single example?
@biscuitvile
Copy link

@coreyhaines I knew if I creeped up in your gists I'd find something like this. Did you figure out how to disable in a test context?

I like the helpers as well but am thinking a PORO approach may be easier. Inject a NilValidator in some kind of test context. Currently working on this so I'll post whatever I come up with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment