Reputation: 563
Say I have models Foo, Bar, and Baz. There is a validation I want to perform on fields in each of these tables. Since it is the same validation, and I like DRY code, and I'm lazy, I'd like to write the logic for this validation in one place and be able to reference it in the model without having to write more than a single line in each model - Much like making methods available to multiple controllers with the use of ApplicationController.
The implementation would look something like this:
class Foo < ActiveRecord::Base
validates :some_field, :custom_shared_validation
end
class Bar < ActiveRecord::Base
validates :some_other_field, :custom_shared_validation
end
But I'm not sure if this is possible, or, if so, where I am to write it. I do know that one way of extending ActiveRecord::Base is to write Concerns, which I'm under the impression allows you to add methods accessible to all models, but I'm not sure if this practice extends to using these methods as validators in all models.
Upvotes: 0
Views: 412
Reputation: 106430
It's incredibly straightforward to do this with concerns...
module OmniVerifiable
extend ActiveRecord::Concern
included do
validates :field, :custom_shared_validation
end
end
...but that's if the fields are the same across all of the models you're validating.
If they're not, then you've got to choose between the worse of the two: either you author a function to bring back the custom field that you want in each model, or you bite the bullet and write the validation in each model.
My advice would be to write out the validations individually since conceptually they concern different fields. If they're different fields, then you'll be doing repeat work anyway. Don't take DRY too far as to make your code terse and unreadable.
Upvotes: 2
Reputation: 4255
See http://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations
Just to recap in case that link changes at some point, in Rails 4 you would write a class that subclasses either ActiveModel::Validator or ActiveModel::EachValidator. That class needs to implement either a validate
or a validate_each
method respectively. Then you can use it in any of your models, or any class that has ActiveModel::Validations mixed in.
Upvotes: 1