Lord Sarevok

Desarrollador web

Validador para contar el mínimo número de palabras que puede tener un atributo de ar

December 15th 2011

Hoy 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!)