Vardarac
Vardarac

Reputation: 563

Custom validations - for all models

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

Answers (2)

Makoto
Makoto

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

sockmonk
sockmonk

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

Related Questions