Where are the main validators for working with Form objects and regular Rails models?
Following the concept of untying forms from a save layer in Rails. I set up a Cage form object that creates two objects together ... say Animal and Plant .
The following examples of form objects are from http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ or https://github.com/solnic/virtus or https://github.com/makandra/active_type , each of which shows that the form object itself has validations ... no problem ... some of the advantages include the ability to validate objects in a more context-sensitive way.
Problem:
class Animal < ActiveRecord::Base validates :color, presence: true validate :only_one_brown private def only_one_brown if some_complex_thing errors.add(:color, 'can not have more than one brown animal.') end end end class Plant < ActiveRecord::Base validates :color, presence: true end class Cage include Virtus.model
How to check the correctness of the "only one brown" rule for animals:
- Too much duplication.
- A lot of code to make Cage still act as an AR model.
If we do not duplicate the verification code when "only one brown" is false, Cage has no error for it ... we will raise what the capture and processing controller requires from the controller, which is bad.
If we duplicate the code, and if there are several user checks, we duplicate a lot of code, and every other form object that deals with Animal needs duplicate checks.
If we completely move the verification code from Animal to Cage, a similar problem: all objects that interact with Animal should be aware of the "only one brown" rule, which simply duplicates validators and opens up an easy way to forget to provide it somewhere.
If we move the array of Animal errors to Cage's, the Animal error is at :color , which is ambiguous for Cage and shows an error in the attribute name that the client never sent. If you want to match the Animal Cage error keys, now you need to save a map for each shape object, to feel smelly.
Are there any good patterns or ways to deal with this situation? I feel this is very common when you start using form objects, but all the examples are pretty trivial.
Thanks in advance!