Skip to content

Instantly share code, notes, and snippets.

@alessandro-fazzi
Last active June 23, 2023 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alessandro-fazzi/e9c8f9c31d317ddccef38bb864c06a4d to your computer and use it in GitHub Desktop.
Save alessandro-fazzi/e9c8f9c31d317ddccef38bb864c06a4d to your computer and use it in GitHub Desktop.
[study] Method's parameters validation
module ValidatableMethods
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def validated(method_name, &block)
mod = Module.new
mod.define_method(method_name) do |*args, **kwargs|
begin
yield(*args, **kwargs)
super(*args, **kwargs)
rescue NoMatchingPatternError, ArgumentError => e
message = "Invalid argument for method #{method_name}: #{e.message} in #{e.backtrace.first}"
# Print for experimenting purpose, but the exception should be re-raised
p message
# raise ArgumentsValidationError.new(message)
end
end
instance_method(method_name).owner.prepend(mod)
end
end
class ArgumentsValidationError < StandardError; end
end
class Foo
include ValidatableMethods
validated def kwargs_only(a:, b:)
p "Success! Your params are: #{a}, #{b}"
end do |**kwargs| kwargs => {a: Integer, b: Array[String, Symbol]} end
validated def positional_only(a, b)
p "Success! Your params are: #{a}, #{b}"
end do |*args| args => [Integer, Array[String, Symbol]] end
validated def mixed(a, b:)
p "Success! Your params are: #{a}, #{b}"
end do |*args, **kwargs|
args => [Integer]
kwargs => {b: Array[Integer, String]}
end
end
obj = Foo.new
obj.kwargs_only
obj.kwargs_only 1, 2
obj.kwargs_only 1, [2, 'three']
obj.kwargs_only '1', ['2', :three]
obj.kwargs_only 1, ['2', :three]
obj.kwargs_only a: '1', b: 2
obj.kwargs_only a: 1, b: [2, 'three']
obj.kwargs_only a: 1, b: ['2', :three]
obj.positional_only
obj.positional_only 1, 2
obj.positional_only 1, [2, 'three']
obj.positional_only '1', ['2', :three]
obj.positional_only 1, ['2', :three]
obj.positional_only a: '1', b: 2
obj.positional_only a: 1, b: [2, 'three']
obj.positional_only a: 1, b: ['2', :three]
obj.mixed
obj.mixed 1, 2
obj.mixed 1, [2, 'three']
obj.mixed '1', ['2', :three]
obj.mixed 1, ['2', :three]
obj.mixed a: '1', b: 2
obj.mixed 1, b: [2, 'three']
obj.mixed 1, b: ['2', :three]
# binding.irb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment