Skip to content

Commit

Permalink
Simplify defining new custom type
Browse files Browse the repository at this point in the history
  • Loading branch information
imdrasil committed Oct 16, 2018
1 parent 93ed64d commit e75c7e6
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 80 deletions.
1 change: 0 additions & 1 deletion lib/envied.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
require 'envied/coercer'
require 'envied/coercer/envied_string'
require 'envied/variable'
require 'envied/type'
require 'envied/configuration'

class ENVied
Expand Down
90 changes: 50 additions & 40 deletions lib/envied/coercer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,55 @@ class ENVied::Coercer
SUPPORTED_TYPES = %i(hash array time date symbol boolean integer string uri float).freeze

class << self
def built_in_type?(type)
SUPPORTED_TYPES.include?(type)
def base_type?(type)
name = type.to_sym.downcase
supported_types.include?(type)
end

def custom_type?(type)
custom_types.key?(type)
def supported_types
SUPPORTED_TYPES
end
end

# Custom types container.
#
# @example
# ENVied::Coercer.custom_types[:json] =
# ENVied::Type.new(:json, ->(str) { JSON.parse(str) })
#
# @return
def custom_types
@custom_types ||= {}
end
def_delegators :'self.class', :base_type?

def supported_types
SUPPORTED_TYPES + custom_types.keys
end
# Whether or not Coercer can coerce strings to the provided type.
#
# @param type [#to_sym] the type (case insensitive)
#
# @example
# ENVied::Coercer.new.supported_type?('string')
# # => true
#
# @return [Hash] of type names and their definitions.
def supported_type?(type)
self.class.base_type?(type) || custom_type?(type)
end

# Whether or not Coercer can coerce strings to the provided type.
#
# @param type [#to_sym] the type (case insensitive)
#
# @example
# ENVied::Coercer.supported_type?('string')
# # => true
#
# @return [Hash] of type names and their definitions.
def supported_type?(type)
name = type.to_sym.downcase
built_in_type?(name) || custom_type?(name)
end
# Whether or not Coercer has the provided type as a custom one.
#
# Custom data type can be registered using Configuration#type method.
#
# @param type [#to_sym] the type (case insensitive)
#
# @example
# ENVied::Coercer.new.custom_type?('string')
# # => false
#
# @return [Hash] of type names and their definitions.
def custom_type?(type)
name = type.to_sym.downcase
custom_types.include?(name)
end

def_delegators :'self.class', :supported_type?, :supported_types, :custom_types
# List of custom types.
def custom_types
@custom_types ||= []
end

def supported_types
self.class.supported_types + custom_types
end

# Coerce strings to specific type.
#
Expand All @@ -58,18 +68,18 @@ def supported_type?(type)
#
# @return [type] the coerced string.
def coerce(string, type)
if self.class.built_in_type?(type)
coerce_method_for(type.to_sym)[string]
elsif self.class.custom_type?(type)
custom_types[type].coerce(string)
else
raise ArgumentError, "#{type.inspect} is not supported type"
end
method = coerce_method_for(type)
raise ArgumentError, "#{type.inspect} is not supported type" unless method
method.call(string)
end

def coerce_method_for(type)
return nil unless supported_type?(type)
coercer.method("to_#{type.downcase}")
method_name = "to_#{type.downcase}"
if base_type?(type)
coercer.method(method_name)
elsif custom_type?(type)
method(method_name)
end
end

def coercer
Expand Down
3 changes: 2 additions & 1 deletion lib/envied/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def variable(name, *args)
end

def type(name, &block)
coercer.custom_types[name] = Type.new(name, block)
coercer.custom_types.push(name.to_sym).uniq!
coercer.define_singleton_method("to_#{name}", &block)
end

def group(*names, &block)
Expand Down
22 changes: 0 additions & 22 deletions lib/envied/type.rb

This file was deleted.

11 changes: 4 additions & 7 deletions spec/coercer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,10 @@ def coerce_to(type)
let(:coerce) { coerce_to(:json) }

before do
coercer.custom_types[:json] =
ENVied::Type.new(
:json,
lambda do |raw_string|
JSON.parse(raw_string)
end
)
coercer.custom_types.push(:json)
coercer.define_singleton_method("to_json") do |raw_string|
JSON.parse(raw_string)
end
end

it 'converts strings to defined custom type' do
Expand Down
10 changes: 7 additions & 3 deletions spec/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
end

describe '#type' do
subject { config.coercer.custom_types }
# subject { config.coercer.custom_types }

let(:coercer) { ->(raw_string) { Integer(raw_string) ** 2 } }
let(:config) do
Expand All @@ -51,8 +51,12 @@
end
end

it 'creates type with given coercing block' do
is_expected.to include(power_integer: ENVied::Type.new(:power_integer, coercer))
it 'registers new custom method' do
expect(config.coercer).to respond_to(:to_power_integer)
end

it 'defines new coercing method in coercer instance' do
expect(config.coercer.method(:to_power_integer).source).to eq(coercer.source)
end
end

Expand Down
7 changes: 1 addition & 6 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,4 @@

$:.unshift File.expand_path("../../lib", __FILE__)
require 'envied'

RSpec.configure do |config|
config.before do
ENVied::Coercer.custom_types.clear
end
end
require 'pry'

0 comments on commit e75c7e6

Please sign in to comment.