App Rail Airtable

App Rail Airtable is a micro-framework based on Sinatra and Airrecord which faciliates use of Airtable as a backend for App Rail Apps. You can deploy a template repo to Heroku for fast start.

Installation

Add this line to your application's Gemfile:

gem 'app_rail-airtable'

Usage

App Rail Airtable has two important concepts, models and servers.

Models

App Rail Airtable makes the following assumptions

  1. Your App will connect to a single Airtable Base
  2. Your Airtable Base implements a normalised datamodel
  3. Your tables in Airtable are plural versions of the models you create in Ruby

API keys have account scope in Airtable so it is recommended to create a new account for each project so that API keys do not leak data, e.g. bob+@gmail.com. You can share the project with your main account so you don't need to login to separate accounts for each project.

You should create a model class for each table you want to use in your App. Model classes should extend AppRail::Airtable::ApplicationRecord and define table name and associations

To provide support for routes, models can implement

  • ar_list_item (index)
  • ar_stack (show)
  • self.create_as_json (create)
  • self.update_as_json (update)

In order to support authentication you should create a class (normally User) and inherit from AppRail::Airtable::AuthenticationRecord. Your table needs Email, Password Hash and Access Token columns.

Servers

You should create a single server which extends AppRail::Airtable::Sinatra.

App Rail Airtable provides two helpers to generate routes

resources(name, only:) Creates routes that map to a table. It delegates from the route to a model method

  • index to ar_list_item
  • show to ar_stack
  • create to self.create_as_json
  • update to self.update_as_json

authenticable_resources(name, , only:) Acts as resources but also takes a block of routes. Those nested routes will all call the authenticate! helper method before running. The authenticate! helper will call a lookup helper find_authenticatable_resource(access_token:) with the bearer token found in the HTTP_AUTHORIZATION header, which should be used to look up the correct object or return nil if none is found (resulting in a 401 response).

Generator

bin/ara_generator <output_directory> <airtable_api_key> <airtable_base_id> [<json_schema>]

Example

bin/ara_generator ./test key1234567890 appwertyuiop '{"tables": [{"name": "DailyLogs", "fields": [{"name": "Date", "type": "date"}, {"name": "Score", "type": "integer"}], "associations": [{"name": "User", "type": "belongs_to", "model": "User"}], "ar_class_methods": [{"name": "ar_list_item", "properties": [{"type": "text", "value": "date"}, {"type": "detail_text", "value": "score"}]}], "ar_instance_methods": [{"name": "ar_stack_item", "properties": [{"type": "text", "label": "Date", "value": "date"}, {"type": "button", "label": "Score", "value": "score", "modalWorkflow": "", "style": "primary", "onSuccess": "forward", "sfSymbolName": ""}]}]}, {"name": "Users", "fields": [{"name": "Email", "type": "string"}, {"name": "Password Hash", "type": "string"}, {"name": "Access Token", "type": "string"}], "associations": [{"name": "DailyLogs", "type": "has_many", "model": "DailyLog"}], "authenticatable": "True"}]}'

You can find more examples of schemas in /examples/schemas

Debugging

Listing Existing Routes

To get a complete list of the available routes in your Sinatra application, run the following code snippet:

Server.routes.map do |method, routes|
    routes.map { |r| r.first.to_s }.map do |route|
      "#{method.rjust(7, ' ')} #{route}"
    end
  end.flatten.sort.each do |route|
    puts route
  end

Output:

    GET /mock_items
    GET /mock_items/:id
    PUT /mock_items/:id
   HEAD /mock_items
   HEAD /mock_items/:id
   POST /mock_items

License

The gem is available as open source under the terms of the MIT License.