Subscribe now

Introduction to Formulae [09.05.2017]

  • What is this
  • What it does
  • How it is divided:
    • Formulae React
    • Formulae
    • Formulae Example
  • How we built it
  • A live example

Formulae: an MIT-licensed form builder, written in Rails and React.

At DailyDrip we put a lot of effort into and behind open source software. Our friends at the Church of the Highlands needed a form builder, so we worked together to build and open source Formulae. Its back end is a web interface and API written in Ruby on Rails, and a client app written in React builds the final user experience. Let’s look at how to implement it in your own project.

Above you can see a demo of the form building interface, and you can try out a demo here.

Using Typeform you can create a custom form with detailed sections, reorder questions, add dependent questions, and share your form with people. Formulae is similar. Our project is divided up as follows:

An API built in Ruby on Rails. A React-based npm package that can administer and respond to forms. A Ruby gem that can communicate with the back-end.

As a proof of concept, we also have an example Rails application using all of this. We will show you how to implement Formulae this week.

Let's have a quick rundown of each part of the project.

Formulae

We have a back-end written in Ruby on Rails. Our most important models are: Form, Application, Section, and Question.

A Form has many Sections. A Section has many Questions. A Question can have many Choices.

The API is a simple Rails API with some authorization, and an ActiveAdmin-based administrative interface. We use Active Model Serializers to define our serialization format.

For example, here you can see our FormSerializer:

# frozen_string_literal: true

class FormSerializer < ActiveModel::Serializer
  attributes :id, :application, :completion_content

  has_many :sections
  has_many :questions
end

It's really handy using this to build serializers. Defining our JSON encodings strictly also makes it much simpler to build an API client.

We are testing our API using rspec-api-documentation, which generates nice-looking API documentation from our test suite. We will talk more about it in the episode on the back-end.

Formulae React

The administrative interface and the component to respond to a form is written in React. We have used Redux and ImmutableJS, and we wrote our project as a library. To kickstart our project, we began it with create-react-app.

We loved using flow as a static type checker. We used flow together with all our code, especially with Immutable. If you use Immutable Records a lot -- and we do -- you lose some of the benefit of flow presently. Still, it’s worth it.

We have written explicit encoders and decoders, for sending and receiving data from the API. This allows us to easily set up the boundaries of our system. With this, our internal code can talk in our strictly defined types, rather than passing around JavaScript objects and hoping for the best. We wrote more about being explicit with decoders, like Elm does, in the DailyDrip blog](https://www.dailydrip.com/blog/using-decoders-in-your-api-the-boundary-between-two-worlds.html).

We really enjoyed using flow and immutable together.

// @flow

import { Record, List } from "immutable";
import SectionType from "./SectionType";

export default class FormType
  extends Record({
    id: "",
    applicationId: "",
    sections: List(),
    completionContent: "",
    persisted: false
  }) {
  id: string;
  applicationId: string;
  sections: List<SectionType>;
  completionContent: string;
  persisted: boolean;
}

Here you can see an example of our Form Type. We have types for each attribute and our Type is an immutable record.

Formulae Example

This is a Rails project, and it embeds the formulae project.

We can use the two components we have in our JavaScript package, and then this will be rendered inside our Rails application.

    ReactDOM.render(
      <Provider store={RespondToFormStore}>
        <div>
          <RespondToForm displaySectionsAs="HEADINGS" />
        </div>
      </Provider>,
      document.getElementById("respond-to-form")
    );

    // Example for AdministerForm
    ReactDOM.render(
      <Provider store={AdministerFormStore}>
        <AdministerForm />
      </Provider>,
      document.getElementById("administer-form")
    );

This was really easy.

Live Example

You can see it all working together here. We have this deployed on Heroku. Here is the API running. As you can see, we are using ActiveAdmin to check and manage our data easily.

Here is our Rails application, and it has formulae react rendered as a react component. We are using Rails 5.1, and we run this with webpack.

We already have some questions here, let's create a section. We can change the name of the section, and create multiple questions for this section. The question type can be address, paragraph text, single line next, drop down list, and others.

Let's create a single line text. The question will be: “Is it not awesome?”

Let's save that. And we can see this form rendered. The rendering of the form is done by another component. Here you will find all questions, including the one we have just created.

Summary

Today we had a quick overview of the entire Formulae project. In the next episodes, we will dive into more details for each part of the entire solution. Stay tuned!

Resources