Skip to content

Instantly share code, notes, and snippets.

@TylerRick
Created December 15, 2011 23:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TylerRick/1483504 to your computer and use it in GitHub Desktop.
Save TylerRick/1483504 to your computer and use it in GitHub Desktop.
Custom Validator that automatically provides the %{allowed_options} interpolation variable for use in your error messages
en:
activerecord:
errors:
messages:
restrict_to: "is not one of the allowed options (%{allowed_options})"
class RestrictToValidator < ActiveModel::EachValidator
ErrorMessage = "An object with the method #include? or a proc or lambda is required, " <<
"and must be supplied as the :allowed_options option of the configuration hash"
def initialize(*args)
super
@allowed_options = options[:allowed_options]
end
def check_validity!
unless [:include?, :call].any?{ |method| options[:allowed_options].respond_to?(method) }
raise ArgumentError, ErrorMessage
end
end
def allowed_options(record)
@allowed_options.respond_to?(:call) ? @allowed_options.call(record) : @allowed_options
end
def allowed_options_string(record)
allowed_options = allowed_options(record)
if allowed_options.is_a?(Range)
"#{allowed_options}"
else
allowed_options.to_sentence(last_word_connector: ', or ')
end
end
def validate_each(record, attribute, value)
allowed_options = allowed_options(record)
inclusion_method = inclusion_method(allowed_options)
unless allowed_options.send(inclusion_method, value)
record.errors.add(attribute, :restrict_to,
options.except(:in).merge!(
value: value,
allowed_options: allowed_options_string(record)
)
)
end
end
private
# In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
# range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
# uses the previous logic of comparing a value with the range endpoints.
def inclusion_method(enumerable)
enumerable.is_a?(Range) ? :cover? : :include?
end
end
@TylerRick
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment