163 lines
4.3 KiB
Markdown
163 lines
4.3 KiB
Markdown
|
# ParamValidation
|
||
|
|
||
|
A standalone and simple ruby hash validation lib, useful for validating the data passed to your functions.
|
||
|
|
||
|
```rb
|
||
|
new_charge_validation = {
|
||
|
amount: {
|
||
|
required: true
|
||
|
},
|
||
|
stripe_card_token: {
|
||
|
required: true,
|
||
|
format: /^tok_.*$/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
def update_database(data)
|
||
|
ParamValidation.new(data, new_charge_validation)
|
||
|
# do stuff
|
||
|
return result
|
||
|
end
|
||
|
```
|
||
|
|
||
|
The above checks the `:amount` and `:stripe_card_token` keys inside the `data`
|
||
|
hash and runs validations on them. If a value is invalid, an exception is
|
||
|
thrown. The exception can be handled outside your function call, typically in a
|
||
|
controller/router or in a test suite.
|
||
|
|
||
|
An exception is thrown for each failure.
|
||
|
|
||
|
## ParamValidation::Error
|
||
|
|
||
|
The ParamValidation::Error object has the following information on it:
|
||
|
|
||
|
```rb
|
||
|
begin
|
||
|
update_database(data)
|
||
|
rescue ParamValidation::Error => e
|
||
|
e.message # string validation failure message
|
||
|
e.val # value that failed validation
|
||
|
e.key # key name of the above value inside the data hash
|
||
|
e.name # name of the validator that failed
|
||
|
rescue Exception => e
|
||
|
# a non-validation exception
|
||
|
end
|
||
|
```
|
||
|
|
||
|
## Using in Rails
|
||
|
|
||
|
To handle validation exceptions from the controller, you can add a custom helper function in your ApplicationController like this:
|
||
|
|
||
|
```rb
|
||
|
def render_json(&block)
|
||
|
begin
|
||
|
result = yield block
|
||
|
rescue ParamValidation::Error => e
|
||
|
return {status: 422, json: {error: e.message, key: e.key}}
|
||
|
rescue Error => e # a non-validation related exception
|
||
|
return {status: 500, json: e}
|
||
|
end
|
||
|
return {status: 200, json: result}
|
||
|
end
|
||
|
```
|
||
|
|
||
|
With the above, you can simply call render_json on your validated function call:
|
||
|
|
||
|
```rb
|
||
|
UsersController < ApplicationController
|
||
|
def update
|
||
|
render_json{ update_user(params[:user]) }
|
||
|
end
|
||
|
end
|
||
|
```
|
||
|
|
||
|
```rb
|
||
|
update_validation = {
|
||
|
email: {
|
||
|
presence: :optional,
|
||
|
format: email_regex
|
||
|
}
|
||
|
}
|
||
|
|
||
|
def update_user(params)
|
||
|
ParamValidation.new(params, update_validation)
|
||
|
end
|
||
|
```
|
||
|
|
||
|
### built-in validators
|
||
|
|
||
|
- required: value must be non-nil
|
||
|
- absent: value must be nil
|
||
|
- not_included_in: value must not be in array
|
||
|
- included_in: value must be in array
|
||
|
- format: value must match regex
|
||
|
- is_integer: value must look like an integer (can be a string)
|
||
|
- is_float: value must look like a float (can be a string)
|
||
|
- min_length: array value must have length >= min
|
||
|
- max_length: array value must have length <= max
|
||
|
- length_range: array value must have length within given range
|
||
|
- length_equals: array value length must equal given arg
|
||
|
- equals: value must equal given arg
|
||
|
- min: value must be >= arg
|
||
|
- max: value must be <= arg
|
||
|
- in_range: value must be within the given range
|
||
|
|
||
|
### custom validators
|
||
|
|
||
|
ParamValidation.add_validator takes a name and a block. That block performs the
|
||
|
validations and simply returns true/false. The block takes three params: the
|
||
|
actual value to validate, and the argument provided in the validation hash, and
|
||
|
the entire data hash being validated.
|
||
|
|
||
|
```rb
|
||
|
# You can use other validators inside a new validator
|
||
|
ParamValidation.add_validator(:dollars) do |val, arg, data|
|
||
|
ParamValidation.validators[:format](val, /^\$\d+\.(\d\d)$?, data)
|
||
|
end
|
||
|
|
||
|
# # Validators that don't need an argument typically just get 'true' passed in
|
||
|
# ParamValidation.new(params, {
|
||
|
# amount: { dollars: true }
|
||
|
# })
|
||
|
|
||
|
# Other examples
|
||
|
|
||
|
# Uniqueness validation (of course it may be better to use the UNIQUE constraint in sql)
|
||
|
ParamValidation.add_validator(:unique) do |val, arg, data|
|
||
|
Qx.select("COUNT(*)").from(:table).where(name: val).first['count'] == 0
|
||
|
end
|
||
|
```
|
||
|
|
||
|
### custom validation messages
|
||
|
|
||
|
Within a validation instance, you can set a custom message with the :message key.
|
||
|
|
||
|
```rb
|
||
|
ParamValidation.new(params, {
|
||
|
amount: {
|
||
|
dollars: true,
|
||
|
message: 'Please enter a dollar amount'
|
||
|
}
|
||
|
})
|
||
|
```
|
||
|
|
||
|
To change the global default message, simply use ParamValidation.set_message(:validation_name, &block).
|
||
|
|
||
|
```rb
|
||
|
ParamValidation.set_message(:dollars) do |h|
|
||
|
"#{h[:key]} must be in dollars"
|
||
|
end
|
||
|
```
|
||
|
|
||
|
The `set_message` block receives a hash with some data:
|
||
|
|
||
|
* :key - name of the key in the hash that failed this validation
|
||
|
* :arg - argument to validator (eg format regex)
|
||
|
* :val - actual value that failed validation
|
||
|
* :data - entire data hash that is being validated
|
||
|
|
||
|
|
||
|
#### internationalization -- TODO!
|
||
|
|
||
|
Internationalization support is not yet in place; please make a PR for it!
|