Recline with Rails

Seamless form management for React using GraphQL.

Work in progress.

What is this?

This is a work in progress that is used for exposing data models through GraphQL for the purpose of building seamless forms.

The goal here is to provide an interface between the backend and frontend of web applications to control how form inputs should look and function with reusable components. Furthermore to allow customization by creating extensions to existing field components and foster a collection of these extensions.

How does it work?

Recline is a layer to provide data-backed instructions for how to display and validate forms for your ActiveRecord and ActiveModel object types. The heart of Recline is within GraphQL::Rails::ActiveReflection providing the core schema for reflecting upon models.

This layer augments the core schema to facilitate the display of forms through the set of React Javascript components that will be released under the same name. This is done through what is called Appearance types. These component types are responsible for coercing inputs and outputs to the proper formats, and validating input through the reflections provided over GraphQL.

By default, database types are mapped to a set of Appearance types:

Recline.default_appearance_types = {
  string: :string,
  text: :text,
  integer: :number,
  float: :number,
  decimal: :number,
  boolean: :toggle,
  date: :date,
  datetime: :datetime,
  timestamp: :datetime
}

Help me explain this better: Create a Pull Request

Installation

To begin, install the gem by adding it to the Gemfile:

  gem 'recline'

Add the following line to an object type that you would like to expose:

  implements Recline::Model.interface, inherit: true

And that's it! This will add a _model field to your object type that will expose any field that can be mapped to an ActiveModel/ActiveRecord attribute.

Example query fragment:

fragment on YourObjectType {
  _model: ReclineModel {
    attributes: [ReclineAttribute] {
      name: String
      field_name: String
      appearance: ReclineAppearance

      validators: [ActiveReflectionValidator] {
        absence: Boolean
        presence: Boolean
        uniqueness: Boolean
        with_format: String
        without_format: String
        min_length: Integer
        max_length: Integer
        inclusion: [String]
        exclusion: [String]
      }

      validate(int: Integer, str: String, float: Float, bool: Boolean): ActiveReflectionValidation {
        valid: Boolean
        errors: [String]
      }
    }
  }
}

There are a few types to be aware of:

  • ReclineModel
  • ReclineAttribute
  • ActiveReflectionValidator
  • ActiveReflectionValidation

Via GraphQL::Rails::ActiveReflection

The _model field will resolve to whatever type Schema.resolve_type returns for that object. Only the fields on that type will be exposed as attributes - where name is the attribute name and field_name is the field name that exposed the attribute.

Each of the validators corresponds to the standard Rails validators. Almost all validators for an attribute will be returned, except those that have the if or unless conditionals. This is by design and therefore make note that any conditional validations will have to be performed manually.

There is also the validate(...) field with arguments for standard scalar types. Any one of the arguments can be provided, but only one. The result will contain a valid boolean and a list of errors strings returned from the validators.

In the future all of the validate(...) should be chained for a single call.

Direction

Motivation for this repo is hand in hand with ActiveReflection - where anything that is model specific will be delegated there and anything that is UI specific will reside here.

Needs Help

If you wish to contribute to this project, any pull request is warmly welcomed.

Todo

Rules for complex default types

  • [ ] Dropdown when attribute has inclusion validator and more than three options
  • [ ] Radio when attribute has inclusion validator and less than three options ### Appearance options
  • [ ] Precision and scale for number types
  • [ ] Date and time format types
  • [ ] Toggle off/on label text

Meta

  • [ ] Documentation
  • [ ] Examples
  • [ ] Unit Tests

Credits