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.


Add this line to your application's Gemfile:

gem 'app_rail-airtable'


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


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. 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.


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).


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


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


Listing Existing Routes

To get a complete list of the available routes in your Sinatra application, run the following code snippet: do |method, routes| { |r| r.first.to_s }.map do |route|
      "#{method.rjust(7, ' ')} #{route}"
  end.flatten.sort.each do |route|
    puts route


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


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