Introducing Surrealist: a gem to serialize Ruby objects according to a defined schema

The icon was created by Simon Child from Noun Project and is published under Creative Commons License

The initial motivation behind this gem was to have a tool that would make it possible to serialize Ruby objects to JSON format outside of the view context. Another idea was to be able to serialize objects that are not tightly coupled to the database, like decorated objects, for instance. In the company where I work we use Draper for objects decoration, and so if we needed to serialize a decorated object we had to patch #as_json method, or write multiple includes/only’s/excepts, so that decorator’s methods are included.

So I thought that it would be nice if we had one place for one object where the resulting schema that we need to have would be stated in a declarative style. I’ve tried a couple of ways to define that schema and figured out that the most convenient way would be having a hash that describes that schema. Now we have a hash and we know what to place as keys — methods and attributes of the object, but what should be in the values? Their types!

Ruby is of course a language with dynamic type system, but it also has classes for the primitive types, like String or Integer . That would be amazing, I thought, we will have a declarative schema and trivial type checks, so that we are always sure what data do we pass further. API now looks like this:

If using ActiveRecord, adding attributes is also trivial (assuming that User record has fields first_name, last_name, age )

If you need your keys to be in camelBack you can pass optional camelize argument.

You can also specify the types via Dry::Types, a great extendable type system for Ruby, using which you can have such features as coercing, strict types, custom types and more.

Another thing is that Surrealist can deal with nested structures, as well as with nested objects. Nested structures can be useful when you want your JSON output to be different from the object structure:

And with ‘nested objects’ you can have methods that reference other objects, that need to be serialized as well.

If type checks fail at some point, Surrealist::InvalidTypeError will be thrown.

Some other notes:
* You can use instance build_schema method that will build the schema and perform type checks, but return a ruby hash rather than JSON.
* Nil values are allowed by default, so if you want to be strict about data absence, consider using dry-types.
* If you have a parameter that is of boolean type, or if you don’t care about the type, you can use Bool and Any respectively.
* Surrealist requires MRI 2.2 or higher.

On the roadmap we have having root key included, delegating surrealization to parent class, integration with other tools (like ROM or Sequel) and more. Come and tune in, and feel free to create issues and pull requests with ideas or suggestions. Source code with more examples (in specs in particular) is available on GitHub, have a nice day and celebrate Hacktoberfest!

Musician & Developer