High level rule vs custom validation block?

When are you supposed to use a high level rule vs a custom validation block?

I want to verify that the sum of amounts in an array of nested objects is equal to an amount on the main object being validated. Not sure which way exactly I should go about it.

Similar to some of the other stuff I have posted recently {total_amount: 100, items: [{amount: 50}, {amount: 40}]} total_amount would probably have the error message that the amounts don’t sum up.

I know this is not properly documented, but conceptually both rule and validate syntax create high-level rules. These rules are applied as the last validation step, only when individual values that they depend on passed their basic schema checks.

In general rule syntax should be used when its DSL allows you to express validation logic in a concise way, but this syntax has its limitations. In your case, you need to perform various calculations, so it’s not possible using rule syntax, so validate is what you need.

So in my instance I was able to make it work by using the form instance that Reform passes in to validation. At first I used validate, but that left the error hanging out on its own, not actually attached to a specific field. Then I tried doing something like described in the “Dynamic Predicate Arguments” section of the docs with eql?: items_sum where items_sum took the item amounts from the form object Reform passes in and summed them up. That left me with the typical eql? error which I didn’t want.

So finally I ended up just making my own custom predicate that allowed me to attach the error to the total_amount field, with a specific custom error, and a more descriptive name for what was being done.

configure do
  options :form
  def matches_items_sum?(value)
    item_sum = form.items.reduce(0) {|sum, i| sum + i.amount}
    value == item_sum
  end 
end

required(:total_amount).filed(:int?, :matches_items_sum?)