Moving from AR validations to dry-validations


#1

Hi guys,

I’m doing some research and the reasoning behind moving from AR validations into dry-validations. I have a questions for the community:

  • What lead you to move from AR validations into dry-validations?
  • What do you think are the implications of that?
  • What do you think are the benefits?

Thanks in advance for your answers,


#2

For me, separation of concerns. ActiveRecord, by design, handles a lot of concepts including persistence, validation, callbacks etc. This means that while it is simple to use the actual code for ActiveRecord is complex making it harder to work with and change for the maintainers.

By breaking things down in to smaller objects which collaborate to achieve the same end result the code can become easier to think about. Now my object has this one responsibility and I put it together with other objects to build up my system.

As a practical example, with AR I can not save the model unless the validations pass. But I might have a situation where I want to skip a validation, that isn’t easy to do with AR. But if my persistence, model and validations are separate I can have different validation objects for each state I want to persist. It means I can use the same objects in different contexts.

For me contexts is the important part, in simple applications AR is a great choice. It is easy to use and everything is contained within one place, the model. But as an application grows you start to introduce different contexts and more edge cases. This is where having separation of concerns really helps provide flexibility without having to hack around the AR design.


#3

Thanks for your reply @krisleech. Very good points in terms of separation of concern. I still don’t see why not just use ActiveModel::Validations and create your own validations there and remove the explicit validations from any given model that way you can pass the validations that you want per context. Wouldn’t that accomplish the same thing that you are after here?

I’m just asking this questions to understand the overall reasoning around moving from what at least in my perspective AR already provides.

Thanks again,


#4

I still don’t see why not just use ActiveModel::Validations and create your own validations there and remove the explicit validations from any given model

This is a good option, but not everyone is using Rails / ActiveRecord / ActiveModel and thus they would need to add a fairly large dependency just to get validations.

In terms of features I haven’t used dry-validation enough to know how it stacks up against AM::Validations as my requirements thus far have been fairly simple. Initial learning of the DSL aside it has been easy enough to use. Not as easy as ActiveModel::Validation, but not significantly more difficult. This is probably due to familiarity with ActiveModel. It may be that it become easier to perform more complex validations succinctly in dry-validations, compared to ActiveModel::Validations, once the requirements are more complicated, I am yet to find out.

The other thing that springs to mind is that ActiveModel is still complex, it itself has a lot of responsibilities, even if as an end user you don’t use all of them, they are present in the library code and this could make it more challenging to change/understand for the maintainers. This is speculation and could be considered a pro or a con depending on perspective.

What ActiveModel::Validation does have going for it is that it is stable and has plenty of documentation. Dry-validation isn’t yet v1.0 so the DSL could change, I don’t know how likely this would be. I’ve used dry-validation recently without a problem in a few places as an alternative to an ActiveModel based “form object”.

The best I could suggest is to give it a spin and see how it fits your project.


#5

It is 100% going to change, unfortunately.

Hopefully this will make it easier to do more complicated things with it. I’ve been having a hard time with it, but the ActiveModel stuff just doesn’t fit my use-case at all.