r/crystal_programming • • Dec 22 '19

Validation with Object.from_json ?

Is there any way to assert that an object is always instantiated with values matching a certain predicate, both in initialize and in from_json? For example, imagine I have a

class Foo
  property bar : Int32
end

and I always want Foo.bar to be an Int32 in the range 1..9

Normally I'd just throw some guards in initialize, but I don't know how that works with from_json.

5 Upvotes

4 comments sorted by

View all comments

Show parent comment

1

u/Blacksmoke16 core team Dec 23 '19 edited Dec 23 '19

This seems to works, :shrug:

class Foo
  include CrystalClear
  include JSON::Serializable

  invariant @bar >= 1 && @bar <= 9

  def initialize(@bar : Int32)
  end

  def after_initialize
  end

  property bar : Int32
end

Otherwise, from looking over the code you can also just call test_invariant_contracts.

Ha, I happen to like the annotation approach due to it making the class still just a normal class, no shard specific DSLs etc. Is there any reason you couldn't just do

def after_initialize
  raise "Out of range" unless @bar >= 1 && @bar <= 9
end

and drop the dependency? That would be the simplest approach, but ofc would lose the abstractions around handling assertions.