module VacuumCleaner::Normalizations::ClassMethods
Public Instance Methods
List of already normalized attributes, to keep everything safe when calling `normalizes` twice for a certain attribute.
When called for the first time checks it's `superclass` for any normalized attributes.
# File lib/vacuum_cleaner/normalizations.rb, line 22 def normalized_attributes @normalized_attributes ||= [].tap do |ary| superclass.normalized_attributes.each { |a| ary << a } if superclass && superclass.respond_to?(:normalized_attributes) end end
Enables normalization chain for supplied attributes.
@example Basic usage for plain old ruby objects.
class Doctor include VacuumCleaner::Normalizations attr_accessor :name normalizes :name end
@param [Strings, Symbols] attributes list of attribute names to normalize, at least one attribute is required @param [Hash] options optional list of normalizers to use, like +:downcase => true+. To not run the default
normalizer ({VacuumCleaner::Normalizer#normalize_value}) set +:default => false+
@yield [value] optional block to define some one-time custom normalization logic @yieldparam value can be nil
, otherwise value as passed through the default normalizer @yieldreturn should return value as normalized by the block
@yield [instance, attribute, value] optional (extended) block with all arguments, like the object
and
current +attribute+ name. Everything else behaves the same es the single-value +yield+
# File lib/vacuum_cleaner/normalizations.rb, line 48 def normalizes(*attributes, &block) normalizations = attributes.last.is_a?(Hash) ? attributes.pop : {} raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? normalizers = [] normalizers << Normalizer.new unless normalizations.delete(:default) === false normalizations.each do |key, options| begin normalizers << const_get("#{VacuumCleaner.camelize_value(key)}Normalizer").new(options === true ? {} : options) rescue NameError raise ArgumentError, "Unknown normalizer: '#{key}'" end end attributes.each do |attribute| attribute = attribute.to_sym # guard against calling it twice! unless normalized_attributes.include?(attribute) send(:define_method, :"normalize_#{attribute}") do |value| value = normalizers.inject(value) { |v,n| n.normalize(self, attribute, v) } block_given? ? (block.arity == 1 ? yield(value) : yield(self, attribute, value)) : value end original_setter = "#{attribute}#{VacuumCleaner::WITHOUT_NORMALIZATION_SUFFIX}=".to_sym send(:alias_method, original_setter, "#{attribute}=") if instance_methods.include?(RUBY_VERSION =~ /^1.9/ ? :"#{attribute}=" : "#{attribute}=") class_eval <<-RUBY, __FILE__, __LINE__+1 def #{attribute}=(value) # 1. def name=(value) value = send(:'normalize_#{attribute}', value) # 2. value = send(:'normalize_name', value) return send(#{original_setter.inspect}, value) if respond_to?(#{original_setter.inspect}) # 3. return send(:'name_wi...=', value) if respond_to?(:'name_wi...=') return send(:[]=, #{attribute.inspect}, value) if respond_to?(:[]=) # 4. return send(:[]=, :name, value) if respond_to?(:[]=) @#{attribute} = value # 5. @name = value end # 6. end RUBY normalized_attributes << attribute end end end