Validador para contar el mínimo número de palabras que puede tener un atributo de ar
December 15th 2011Hoy me ha hecho falta hacer una validación que cuente un mínimo número de palabras sobre un atributo de un modelo de active record y lo he resuelto así
class WordLimitValidator < ActiveModel::EachValidator
include ActionView::Helpers::SanitizeHelper
def validate_each(object, attribute, value)
raise ArgumentError if options[:min].nil?
if (strip_tags(value.to_s).scan(/\w+/).length <= options[:min].to_i)
object.errors[attribute] << (options[:message] || I18n.t('....'))
end
end
end
Incluyo el SanitizeHelper para quitar los tags htmls que puede incluir el atributo, para el caso que debia resolver era necesario.
Como veis, en options nos vienen los parámetros que le definimos en el modelo como min: 150, si quisiéramos añadir máximos, allows, if, unless etc.. no hay más que pasárselo por parámetro y trabajarlo en el código interno del validador.
Si quereis ejemplos más complejos, visitad el rdoc de cualquier validador de los que trae el framework y os puede servir de guia, a mi me vino bien :) (NumericalityValidator)
El test que le he realizado más o menos queda así
# encoding: UTF-8
require 'spec_helper'
describe WordLimitValidator do
describe "validate_each" do
describe "word_limit" do
it "emtpy should be invalid" do
event = Event.new
WordLimitValidator.new({attributes: event.attributes, min: 150}).validate_each(event, :long_description, '')
event.errors[:long_description].should be_present
end
it "with 149 word should be invalid" do
event = Event.new
WordLimitValidator.new({attributes: event.attributes, min: 150}).validate_each(event, :long_description, ('word ' * 149))
event.errors[:long_description].should be_present
end
it "with 150 word should be valid" do
event = Event.new
WordLimitValidator.new({attributes: event.attributes, min: 150}).validate_each(event, :long_description, ('word ' * 150))
event.errors[:long_description].should be_blank
end
it "with 150 words adn html should be valid" do
event = Event.new
WordLimitValidator.new({attributes: event.attributes, min: 150}).validate_each(event, :long_description, long_event_description)
event.errors[:long_description].should be_blank
end
end
end
end
long_event_description: no es más que un helper que me da un texto largo con tags html
Y para usarlo desde nuestros modelos
validates :long_description, word_limit: {min: 150, message: '...'}
En el episodio pro os enseñaré como hacer natillas que no engordan ^^ ( joke!! :) rbates rocks!)