diff --git a/.rubocop.yml b/.rubocop.yml index 3cde3fe..45b3209 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,6 +10,7 @@ Style/ClassVars: Enabled: true Exclude: - lib/slackify/handlers/base.rb + - lib/slackify/parameter.rb AllCops: TargetRubyVersion: 2.6 diff --git a/lib/slackify.rb b/lib/slackify.rb index b304cde..b5b3952 100644 --- a/lib/slackify.rb +++ b/lib/slackify.rb @@ -4,6 +4,7 @@ require 'slackify/engine' require 'slackify/exceptions' require 'slackify/handlers' +require 'slackify/parameter' require 'slackify/router' module Slackify diff --git a/lib/slackify/handlers/validator.rb b/lib/slackify/handlers/validator.rb index 5915919..442f5f8 100644 --- a/lib/slackify/handlers/validator.rb +++ b/lib/slackify/handlers/validator.rb @@ -72,6 +72,11 @@ def validate_parameters(parameters) next if VALID_PARAMETER_TYPES.include?(type.to_sym) + type.constantize + next if Slackify::Parameter.supported_parameters.include?(type) + + errors << "Invalid parameter type for: #{key}, '#{type}'." + rescue NameError errors << "Invalid parameter type for: #{key}, '#{type}'." end errors diff --git a/lib/slackify/parameter.rb b/lib/slackify/parameter.rb new file mode 100644 index 0000000..f087ff0 --- /dev/null +++ b/lib/slackify/parameter.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Slackify + # Base parameter class that any user defined parameters must inherit from + class Parameter + @@supported_parameters = [] + + class << self + # Any class inheriting from Slackify::Parameter will be added to + # the list of supported parameters + def inherited(subclass) + @@supported_parameters.push(subclass.to_s) + end + + # Show a list of the parameters supported by the app. Since we do + # metaprogramming, we want to ensure we can only call defined parameter + def supported_parameters + @@supported_parameters + end + end + end +end diff --git a/lib/slackify/router.rb b/lib/slackify/router.rb index 2b2a325..2bfd51e 100644 --- a/lib/slackify/router.rb +++ b/lib/slackify/router.rb @@ -80,15 +80,18 @@ def parse_by_spec(spec, raw_arguments) processed_spec = {} spec.each do |key, value| # coerce to the expected type - processed_spec[key] = case value.fetch(:type, 'string') + type = value.fetch(:type, 'string') + processed_spec[key] = case type when :int processed_args[key].to_i when :float processed_args[key].to_f - when :bool + when :boolean ActiveModel::Type::Boolean.new.cast(processed_args[key]) - else + when :string processed_args[key] + else + Object.const_get(type).new(processed_args[key]).parse end end diff --git a/test/dummy/app/handlers/dummy_handler.rb b/test/dummy/app/handlers/dummy_handler.rb index 398e46c..8352da8 100644 --- a/test/dummy/app/handlers/dummy_handler.rb +++ b/test/dummy/app/handlers/dummy_handler.rb @@ -44,5 +44,10 @@ def method_3_command(params) "string: #{params[:command_arguments][:string_param]}, "\ "float: #{params[:command_arguments][:float_param]}" end + + def method_4_command(params) + puts "this takes a user arg; "\ + "user: #{params[:command_arguments][:user_param]}" + end end end diff --git a/test/dummy/app/models/user_param.rb b/test/dummy/app/models/user_param.rb new file mode 100644 index 0000000..bfc8953 --- /dev/null +++ b/test/dummy/app/models/user_param.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class UserParam < Slackify::Parameter + def initialize(value) + @value = value + end + + def parse + if @value == 'W12345TG' + "Doug Edey" + else + "Foo" + end + end +end diff --git a/test/dummy/config/handlers.yml b/test/dummy/config/handlers.yml index 19d2bf6..4749fd2 100644 --- a/test/dummy/config/handlers.yml +++ b/test/dummy/config/handlers.yml @@ -17,3 +17,10 @@ - bool_param: boolean action: method_3_command name: method 3 + + - description: method 4 with a custom parsed parameter + base_command: "method4" + parameters: + - user_param: UserParam + action: method_4_command + name: method 4 diff --git a/test/unit/router_test.rb b/test/unit/router_test.rb index fea9b90..3c11ad5 100644 --- a/test/unit/router_test.rb +++ b/test/unit/router_test.rb @@ -18,6 +18,12 @@ class RouterTest < ActiveSupport::TestCase end end + test "parameters can be processed by a custom parser" do + assert_output(/this takes a user arg; user: Doug Edey/) do + Slackify::Router.call_command('method4 user_param=W12345TG', {}) + end + end + test "Only one command gets called in the event of two regex match. Only the first match is called" do assert_output(/cool_command called/) do Slackify::Router.call_command('wazza foo', {})