diff --git a/lib/envied.rb b/lib/envied.rb index 298628c..f0f07bf 100644 --- a/lib/envied.rb +++ b/lib/envied.rb @@ -4,7 +4,6 @@ require 'envied/coercer' require 'envied/coercer/envied_string' require 'envied/variable' -require 'envied/type' require 'envied/configuration' class ENVied diff --git a/lib/envied/coercer.rb b/lib/envied/coercer.rb index c12858d..303842f 100644 --- a/lib/envied/coercer.rb +++ b/lib/envied/coercer.rb @@ -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. # @@ -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 diff --git a/lib/envied/configuration.rb b/lib/envied/configuration.rb index f1bb22c..136ccc6 100644 --- a/lib/envied/configuration.rb +++ b/lib/envied/configuration.rb @@ -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) diff --git a/lib/envied/type.rb b/lib/envied/type.rb deleted file mode 100644 index a3745ec..0000000 --- a/lib/envied/type.rb +++ /dev/null @@ -1,22 +0,0 @@ -class ENVied::Type - attr_reader :name - - def initialize(name, coercer) - @name = name - @coercer = coercer - end - - def coerce(value) - coercer.call(value) - end - - def ==(other) - self.class == other.class && - name == other.name && - coercer == other.coercer - end - - protected - - attr_reader :coercer -end diff --git a/spec/coercer_spec.rb b/spec/coercer_spec.rb index ef0095c..3f0fb38 100644 --- a/spec/coercer_spec.rb +++ b/spec/coercer_spec.rb @@ -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 diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index dd11149..4df571d 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -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 @@ -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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8d4c188..247001b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -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'