diff options
| author | Michael Herold <opensource@michaeljherold.com> | 2018-08-11 10:50:17 -0500 |
|---|---|---|
| committer | Michael Herold <opensource@michaeljherold.com> | 2018-08-11 11:27:12 -0500 |
| commit | 50898af55a4fd9fac96e5748e59abee3614e786b (patch) | |
| tree | 97a8250aa0bfdbc239719a1e92b2f2c467d101cc /lib | |
| parent | 6ab1e45ef74526fe983b4ed29174b781db00cd24 (diff) | |
| download | hashie-50898af55a4fd9fac96e5748e59abee3614e786b.tar.gz | |
Refactor PropertyTranslation for readability
The original implementation of PropertyTranslation was heavily reliant
longer methods that added a lot of cognitive load for understanding what
should be happening at any given point. This refactor gives names for all
of the steps that happen at each step to make it easier to reason about
bugs and additions.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/hashie/extensions/dash/property_translation.rb | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/lib/hashie/extensions/dash/property_translation.rb b/lib/hashie/extensions/dash/property_translation.rb index 2d28080..25b6499 100644 --- a/lib/hashie/extensions/dash/property_translation.rb +++ b/lib/hashie/extensions/dash/property_translation.rb @@ -40,7 +40,7 @@ module Hashie module PropertyTranslation def self.included(base) base.instance_variable_set(:@transforms, {}) - base.instance_variable_set(:@translations_hash, {}) + base.instance_variable_set(:@translations_hash, ::Hash.new { |hash, key| hash[key] = {} }) base.extend(ClassMethods) base.send(:include, InstanceMethods) end @@ -72,21 +72,16 @@ module Hashie def property(property_name, options = {}) super - if options[:from] - if property_name == options[:from] - raise ArgumentError, "Property name (#{property_name}) and :from option must not be the same" - end - - translations_hash[options[:from]] ||= {} - translations_hash[options[:from]][property_name] = options[:with] || options[:transform_with] + from = options[:from] + converter = options[:with] + transformer = options[:transform_with] - define_method "#{options[:from]}=" do |val| - self.class.translations_hash[options[:from]].each do |name, with| - self[name] = with.respond_to?(:call) ? with.call(val) : val - end - end - elsif options[:transform_with].respond_to? :call - transforms[property_name] = options[:transform_with] + if from + fail_self_transformation_error!(property_name) if property_name == from + define_translation(from, property_name, converter || transformer) + define_writer_for_source_property(from) + elsif valid_transformer?(transformer) + transforms[property_name] = transformer end end @@ -103,26 +98,49 @@ module Hashie end def translations - @translations ||= {}.tap do |h| + @translations ||= {}.tap do |translations| translations_hash.each do |(property_name, property_translations)| - h[property_name] = if property_translations.size > 1 - property_translations.keys - else - property_translations.keys.first - end + translations[property_name] = + if property_translations.size > 1 + property_translations.keys + else + property_translations.keys.first + end end end end def inverse_translations - @inverse_translations ||= {}.tap do |h| + @inverse_translations ||= {}.tap do |translations| translations_hash.each do |(property_name, property_translations)| - property_translations.each_key do |k| - h[k] = property_name + property_translations.each_key do |key| + translations[key] = property_name end end end end + + private + + def define_translation(from, property_name, translator) + translations_hash[from][property_name] = translator + end + + def define_writer_for_source_property(property) + define_method "#{property}=" do |val| + __translations[property].each do |name, with| + self[name] = with.respond_to?(:call) ? with.call(val) : val + end + end + end + + def fail_self_transformation_error!(property_name) + raise ArgumentError, "Property name (#{property_name}) and :from option must not be the same" + end + + def valid_transformer?(transformer) + transformer.respond_to? :call + end end module InstanceMethods @@ -156,6 +174,12 @@ module Hashie fail_no_property_error!(property) unless self.class.property?(property) true end + + private + + def __translations + self.class.translations_hash + end end end end |
