A concern about rails validators, breaking MVC in complex projects

Hi all,

thanks for the input :slight_smile:

Imagine having a Transaction model with a double digit number of input controllers where most of those are tied to this or that payment API with slightly diverging additional fields (one asks for pan, other for pan and cvv, the third one for IBAN only, forth for…),

  1. the PORO form approach with included validators means having dozens of additional form subclasses implemented so you could handle these little differences which mostly come down to one or two extra attributes per form, it also means having to check out the model, controller, form class and view if there’s an error with the attribute list
  2. the with_options :if => should_validate_attribute_x? approach is equivalent to the gist approach, but less invasive and doesn’t require practically reimplementing elements of the validation stack, thank you Matt, very nice thought

However, the form class approach seems The Way to go in general - it definitely feels cleaner, I’m just not 100% bought its the way to go in this particular case, too many special snowflakes. Also, the form class approach seems both dispersed and repetitive in the attribute list mantra department.

At the moment for any given controller action you list the attributes in the form builder, then vast majority of them get listed in the strong_params permit(*args) method, then they get repeated in the delegator/accessor dance + model integration boilerplate in the form class and a part of all of this is already implemented in the model, all of it is quite monotonous, verbose and prone to copy/paste/type errors - and all of this to plug one additional validator in,

while it is cleaner then shoehorning validators onto the instance and watching them interact with model validators with funny side effects in views (“oops you missed 20 fields” on a 5-field form, for example), it does feel kind of fishy.

There’s a definite smell about it, it feels un-rails-ish and I can’t shake away the thought that some of these things can be unified / dryed up with better organization of the way model, controller and view interact, perhaps the most obvious point would be stronger coupling between the form builder class (from the view) and the form class (from the controller) - after all,

  1. anything that’s in the form must end up in the params hash received by the form class
  2. and all of the attributes in the params hash need to have some kind of setter counterpart in the form class,
  3. also certain elements of the controller environment would arguably end up in the form class (strong parameter protected things like current user, for example)
    Thoughts?

@Nick, you mentioned that there are gems that tackle this issue?

@Mrloz, “validate: false” has an unwanted side-effect of skipping *_validate hooks which often end up holding generator methods, this is an antipattern though, one of the ways people go around the “validator in form + multiple form inputs” issue while blindly sticking to the “thin controller, oh boy is that one FAT model” principle

Thanks,

Borna