I am trying to add an email custom validators for my app; However, where should I place the custom validator? (I really do not want to place this validator class inside the model) Is there a cli generator for validator?
class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i record.errors[attribute] << (options[:message] || "is not an email") end end end class Person < ApplicationRecord validates :email, presence: true, email: true end What's the convention location/path for custom validator?
4 Answers
I put them in /app/validators/email_validator.rb and the validator will be loaded automatically.
Also, I don't know if it's your case but you should replace this in your form. If so, a first validation is made before the user reach your controller.
<div> <%= f.label :email %> <%= f.text_field :email, required: true %> </div> By :
<div> <%= f.label :email %> <%= f.email_field :email, required: true %> </div> 6Rails 6
app/models/validators/ is also a sensible directory to house validators.
I choose this directory over others such as app/validators since the validators are context-specific to ActiveModel
app/models/person.rb
class Person < ApplicationRecord validates_with PersonValidator end app/models/validators/person_validator.rb
class PersonValidator < ActiveModel::Validator def validate(record) record.errors.add(:name, 'is required') unless record.name end end config/application.rb
module ... class Application < Rails::Application config.load_defaults 6.1 config.autoload_paths += Dir[File.join(Rails.root, 'app', 'models', 'validators')] end end Specs for the validators would be placed in spec/models/validators/
My validator did not loaded automatically. At least is not showing when I type in the console:
> ActiveSupport::Dependencies.autoload_paths So, I put in my config/application.rb, this line:
config.autoload_paths += %W["#{config.root}/lib/validators/"] 1In rails 6 I had to put them in /app/models/concerns for them to autoload