eji/encodable_validator

View on GitHub
lib/active_model/validators/encodable_validator.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'active_model/validations'

module ActiveModel
  module Validations
    class EncodableValidator < ActiveModel::EachValidator
      def check_validity!
        values = options[:encodings]
        unless values.respond_to?(:all?) and values.all? {|v| v.class <= Encoding} 
          raise ArgumentError, ":encodings must be a array of Encodings"
        end
      end

      def validate_each(record, attr_name, value)
        return if options[:allow_nil] && value.nil?

        unless value.respond_to?(:encode)
          record.errors.add(attr_name, :not_a_encodable_object , options)
          return
        end

        src_enc = value.encoding
        last_enc = nil
        begin
          options[:encodings].each do |enc|
            last_enc = enc
            value.encode(enc, src_enc)
          end
        rescue Encoding::UndefinedConversionError
          record.errors.add(attr_name, :can_not_be_encoded, options.merge(
            :value => value,
            :encoding => last_enc
          ))
          return
        rescue Encoding::InvalidByteSequenceError
          record.errors.add(attr_name, :included_invalid_byte_sequences, options)
          return
        end
      end
    end

    module HelperMethods
      # Usage:
      #   class Person < ActiveRecord::Base
      #     validates_encodable_of :name, :encodings => [Encoding::ISO_2022_JP, Encoding::EUC_JP]
      #   end
      #
      # Configuration options:
      # * <tt>:encodings</tt> - check that a text can be encoded to specified encodings.
      def validates_encodable_of(*attr_names)
        validates_with EncodableValidator, _merge_attributes(attr_names)
      end
    end
  end
end