valid , valid? , valid!

In this article, you’ll learn some interesting Ruby validation techniques. We’ll drive you trhough input and output validation inside ruby applications, the good and bads and some possible solutions.

You are probably already familiar with the different validation layers present in Rails (or other ruby frameworks). Viewing them from the request point of view we have something like:

validation-current

Rack validation gives you content type validation and some extra validations like files and body in multipart requests.

Rails versions >4 comes with strong params, which gives you the ability to define which of the input params are required or allowed, and with a not very exhaustive feature you can define the param type choosing between a short list of types.

Model validations in rails come from the ActiveModel::Validations module, they are awesome and you can do almost any kind of format, inclusion, uniqueness or custom validation there.

Aside from rails we also have:

What is missing

Let’s put it into perspective: if we draw the previous diagram matching sizes with how accurate the validation is in a regular Rails app we will have something like:

validation-perspective

This makes sense, as you are protecting the most precious attribute of your app, the persisted data. But let’s think about it from the performance and the security point of view: all kind of validation is good for your app health and the sooner you make it the sooner you will be able to stop the request processing, saving machine resources and adding previous layer security in your app.

So, why not move those sizes around and have a bigger param validation layer? why not include format, types, relations and all the power of the ActiveModel::Validations in the controller param validator layer?

This idea jumped into our minds during the new API architecture design, and we came up with something called ParamValidators. The idea is dead simple: use plain ruby objects with ActiveModel::Validations as service objects to validate and extract params before the controller uses them.

Param Validators

Let’s start with the base object handling the logic methods to build param validator ruby objects:

In this basic base object we take care of three things:

  • Collect the defined attributes with attr_accessor (allowed ones)
  • Initialize them with the given param keys
  • Provide a method to return a HashWithIndifferentAccess after assignation validation and parsing.

Now we are able to create objects like:

This is just a meta function allowing you to instantiate a ParamValidator object with the current request params, validate it (rendering a :bad_request response with the json errors if is not valid) and memoizing the validated, filtered and parsed Hash. In short, it allows you to easily use ParamValidator objects in a controller just like this:

Wrap up

In the last few paragraphs we explored the different validation types and responsibilities in rails applications, understood their use cases and detected the missing parts.

After that we proposed a partial solution to the problem by redifining the architectural way the input validation is built in current rails applications.

Links

We have an open source project here where you can participate or expose your ideas about the ParamValidator thing.

Thanks and happy coding.

 

andresbravog

 

Leave a Reply

Your email address will not be published. Required fields are marked *