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
- Your App will connect to a single Airtable Base
- Your Airtable Base implements a normalised datamodel
- 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+
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
toar_list_item
show
toar_stack
create
toself.create_as_json
update
toself.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.