Add validation classes

This reworks how all the `*_node` methods are defined to pull the common patterns of mutation (before/after) and validation out.
Given this is called range, I expected it to take a ruby range!

```
def initialize(range)
  @range = range
end

def test
  range.cover?(value)
end

def message
  "must be between #{range.min} and #{range.max}
end
```

#JobDone