Parametron
This simple library implements DSL for validating and type casting input parameters for method.
Installation
Add this line to your application's Gemfile:
gem 'parametron', '>= 0.3'
And then execute:
$ bundle
Or install it as:
$ gem install parametron
Usage
class VictimStrict
include Parametron # <- should be at the top of class/module
params_for(:fetch, strict: true) do
required :city, validator: /\w+/
required :year, validator: /\d{4}/
optional :title, validator: ->(str){ str != "Moscow" }, cast: ->(str){ str.upase }
optional :number, validator: /\d+/, default: 42
optional :gears, default: ->(obj){ choose_by(obj) }
optional :weel_d, as: :weel_diameter
optional :load, cast: Float
end
def fetch params
# .. do something useful with params
end
endThe main aim of this small gem is to implement base AOP (aspect oriented programming) to separate validation, conversion and setting defaults for methods from real businnes logic which should be the only body of that method without validators, convertors, default setters overhead.
In order to get this functionality you only need to include Parametron module into top of your class and after that describe desired incoming parameters for method.
class Example
include Parametron # <- should be at the top of class/module
params_for(:fetch) do
...
end
endClass method params_for accepts one or two arguments: first is symbolized name of method of interest and second one (optional) is hash of two options:
-
strictwhich is defaultly set tofalse -
rejectwhich is defaultly set tofalsetoo
strict when set to true means that when you call your method and try to send unknown (not described) key - it raise error Parametron::ExcessParameter
reject when set to true reject undescribed keys from method arguments
class ExampleStrict
include Parametron # <- should be at the top of class/module
params_for(:fetch, strict: true) do
optional :one
end
def fetch par
end
end
ex = ExampleStrict.new.fetch({unexpected: 'argument'})
# => raises Parametron::ExcessParameter class ExampleReject
include Parametron # <- should be at the top of class/module
params_for(:fetch, reject: true) do
optional :one
end
def fetch par
par
end
end
ex = ExampleReject.new.fetch({one: '1', unexpected: 'argument'})
p ex
# => {one: '1'}Method params_for should provide description block where you describe required and optional parameters for given method:
params_for(:fetch) do
required :city, validator: /\w+/
required :year, validator: /\d{4}/
optional :title, validator: ->(str){ str != "Moscow" }, cast: ->(str){ str.upase }
optional :number, validator: /\d+/, default: 42
optional :gears, default: ->(obj){ choose_by(obj) }
optional :weel_d, as: :weel_diameter
optional :load, cast: Float
endWhen parameter is required it must present in argument hash.
Instead, parameter described as optional might present but don't must.
All of that parameter descriptors can have such refinements:
-
validatorwithRegexporprocpredicat to be sure that input parameter is valid -
castwhich could be one of:Integer,Float,procto convert input parameter -
defaultto set input parameter to its default value in case if it not presents -
asto rename input parameter name to new one
When cast options is a lambda/proc you could have current input hash and (if need)
original input hash. It is depends of arity of lambda you provide.
If your cast lambda arity is 1 then it receive current value to cast; when its arity is 2
then it receive |current_value, current_casted_parameters| and when its arity is 3
it will get |current_value, current_casted_parameters, original_params|
This could be handy when you want to have access to other parameters from input hash already
casted.
Exceptions
Normally parametron raise exceptions when mandatory required parameter missed,
when cast expect something other than it gets and so on.
You could change this behavior if you need adding exception handler:
params_for(:fetch) do
required :city, validator: /\w+/
required :year, validator: /\d{4}/
on_exception ->(ex) {
# return something other then exception `ex`
return false
}
endContributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request