Module: PowerConverter

Defined in:
lib/power_converter.rb,
lib/power_converter/version.rb

Overview

:nodoc:

Defined Under Namespace

Classes: ConversionError, ConverterNotFoundError

Constant Summary collapse

CONVERSION_METHOD_PREFIX =

When building a dynamic conversion method this is its prefix.

"convert_to_".freeze
CONVERSION_METHOD_REGEXP =

Useful for when you want to know if a method name is a valid conversion method name.

/\A#{CONVERSION_METHOD_PREFIX}(.+)\Z/
VERSION =

:nodoc:

"0.1.0".freeze

Class Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handle attempts to call module level conversions directly off of the PowerConverter module.

Examples:

PowerConverter.define_conversion_for(:boolean) { |input| ... }
PowerConverter.convert_to_boolean(a_value)

Parameters:

  • method_name (Symbol)
  • args (Array)

    splat arguements that would be passed on-ward

  • block (#call)

See Also:

Since:

  • 0.0.2



257
258
259
260
261
262
263
264
# File 'lib/power_converter.rb', line 257

def method_missing(method_name, *args, &block)
  named_converter = extract_named_converter_from(method_name)
  if named_converter
    convert(*args, to: named_converter, &block)
  else
    super
  end
end

Class Method Details

.convert(value, options = {}) { ... } ⇒ Object

Convert the given ‘value` via the named `:to` converter. As a short-circuit if the given `value` publicly responds to a `to_<named_converter>` it will use that.

Examples:

PowerConverter.convert('true', to: :boolean)
class Foo
  def to_bar
    :hello_world
  end
end

PowerConverter.convert(Foo.new, to: :bar)
=> :hello_world

Parameters:

  • value (Object)

    the thing that you will be converting

  • options (Hash) (defaults to: {})

    the options used to perform the conversion

Options Hash (options):

  • :to (Symbol)

    the named_conversion that has been registered

Yields:

  • Yield control to caller if the value could not be converted; This is a good fallback mechanism.

Returns:

  • (Object)

    the resulting converted object

Raises:

See Also:

Since:

  • 0.0.1



154
155
156
157
158
159
160
161
162
# File 'lib/power_converter.rb', line 154

def convert(value, options = {})
  named_converter = options.fetch(:to)
  scope = options.fetch(:scope, nil)
  return value.public_send("to_#{named_converter}") if value.respond_to?("to_#{named_converter}", false)
  returning_value = converter_for(named_converter).call(value, *scope)
  return returning_value unless returning_value.nil?
  return yield if block_given?
  fail ConversionError.new(value, options)
end

.converter_for(named_conversion) ⇒ #call

Note:

There are no protections for infinite alias loops.

Given the ‘named_conversion` find and retrieve the defined converter.

Examples:

PowerConverter.converter_for(:boolean).call(value)

Parameters:

  • named_conversion (String, Symbol)

Returns:

  • (#call)

    a registered converter

Raises:

See Also:

Since:

  • 0.0.1



220
221
222
223
224
225
# File 'lib/power_converter.rb', line 220

def converter_for(named_conversion)
  key = named_conversion.to_s
  return defined_conversions[key] if defined_conversions.key?(key)
  return converter_for(aliased_conversions[key]) if aliased_conversions.key?(key)
  fail ConverterNotFoundError.new(named_conversion, defined_converter_names)
end

.define_alias(aliased_named_conversion, options = {}) ⇒ Object

You may define an alias of a defined (or to be defined) power converter.

Examples:

PowerConverter.define_alias(:true_or_false, is_alias_of: :boolean)

Parameters:

  • aliased_named_conversion (String, Symbol)

    the name of the conversion that you are declaring.

  • options (Hash) (defaults to: {})

    the options used to perform the conversion

Options Hash (options):

  • :is_alias_of (Symbol)

    the aliased_named_conversion that we will be using for to perform the conversion.

Returns:

  • void

Since:

  • 0.0.4



116
117
118
119
# File 'lib/power_converter.rb', line 116

def define_alias(aliased_named_conversion, options = {})
  @aliased_conversions ||= {}
  @aliased_conversions[aliased_named_conversion.to_s] = options.fetch(:is_alias_of)
end

.define_conversion_for(named_conversion, &converter) {|value| ... } ⇒ Object

TODO:

Make sure that the converter requires at least one parameter.

Note:

If your defined converter returns ‘nil`, it is assumed that the conversion failed and a [PowerConverter::ConversionError] exception will be thrown.

Note:

The conversion module/method that is created may not adhear to the exact idiom (a method defined in CamelCase)

Responsible for defining a conversion method and a “shovel-ready” conversion module; because maybe you want a mixin for convenience reasons.

Examples:

PowerConverter.define_conversion_for :boolean do |input|
  case input
  when false, 0, '0', 'false', 'no', nil then false
  else
    true
  end
end

PowerConverter.convert(object, to: :boolean)
PowerConverter.convert_to_boolean(object)

Parameters:

  • named_conversion (String, Symbol)

    the name of the conversion that you are declaring.

  • converter (#call)

    the callable object that will perform the conversion.

Yields:

  • (value)

    A block that will be used to convert the given value to the named thing.

Yield Returns:

  • returns the named thing.

Returns:

  • void

See Also:

Since:

  • 0.0.1



96
97
98
99
# File 'lib/power_converter.rb', line 96

def define_conversion_for(named_conversion, &converter)
  @defined_conversions ||= {}
  @defined_conversions[named_conversion.to_s] = converter
end

.defined_converter_namesArray

A convenience method for seeing the names of all converters that have been defined.

Returns:

  • (Array)

    of the defined converter’s names

Since:

  • 0.0.1



234
235
236
# File 'lib/power_converter.rb', line 234

def defined_converter_names
  defined_conversions.keys + aliased_conversions.keys
end

.module_for(named_conversion) ⇒ Module

TODO:

Allow for the inclusion of multiple power converter named types.

Note:

This does not allow for the robustness of the .convert method. I’m wondering about its ongoing value.

The means for mixing in a private conversion method; Perhaps as policy you don’t want to expose the public conversion method but instead prefer to leverage private methods.

Examples:

class Foo
  attr_accessor :bar
  include PowerConverter.module_for(:boolean)
  def bar_as_boolean
    convert_to_boolean(@bar)
  end
end

Parameters:

  • named_conversion (String, Symbol)

    the name of the conversion that you are requesting be wrapped in a conversion module.

Returns:

  • (Module)

    a conversion module to use for mixing in behavior

Since:

  • 0.0.1



192
193
194
195
196
197
198
199
200
201
# File 'lib/power_converter.rb', line 192

def module_for(named_conversion)
  Module.new do
    # HACK: I'd prefer to not lean on calling the underlying convert method
    # which means I will likely need some converter builder behavior.
    define_method("#{CONVERSION_METHOD_PREFIX}#{named_conversion}") do |value|
      PowerConverter.convert(value, to: named_conversion)
    end
    private "#{CONVERSION_METHOD_PREFIX}#{named_conversion}"
  end
end