Build Status

AirtableSync

Keep your Ruby on Rails records in sync with AirTable.

Currently only one way Rails => AirTable synchronization.

For the latest changes, see the CHANGELOG.md.

Installation

Add this line to your application's Gemfile:

gem 'airtable_sync'

And then execute:

$ bundle

Then run the install generator:

bundle exec rails generate airtable_sync:install

Usage

Configuration options

In config/initializers/airtable_sync.rb you can specify configuration options:

  1. api_key - In order to use this gem, you need to generate AirTable API key: https://airtable.com/create/apikey
  2. airtable_base_id - you can set airtable_base_id here or override def airtable_base_id in your model. More on this below.
  3. skip_airtable_sync - if set to true, AirtableSync will not sync records to AirTable. This is useful for development and test environments where you don't want to sync records to AirTable.

Example:

AirtableSync.configure do |config|
  config.api_key = ENV.fetch('AIRTABLE_API_KEY')
  config.skip_airtable_sync = ActiveModel::Type::Boolean.new.cast(ENV.fetch('SKIP_AIRTABLE_SYNC'))
end

Create AirTable tables

You need to create the AirTable base(s) and table(s) yourself.

Add AirtableSync to models

For each model that you want to sync to AirTable, you need to run the connection generator:

bundle exec rails generate airtable_sync:connection Article

Please note that this does not create the AirTable table. You need to already have it or create it manually.

Set airtable_base_id

There are couple of ways how you can set the airtable_base_id to be used.

Set airtable_base_id through configuration

In config/initializers/airtable_sync.rb you can specify airtable_base_id:

AirtableSync.configure do |config|
  config.airtable_base_id = ENV.fetch('AIRTABLE_BASE_ID')
end

Set airtable_base_id in model

# app/models/article.rb

class Article < ApplicationRecord
  include AirtableSync::RecordSync

  def airtable_base_id
    site.airtable_base_id
  end
end

Customize fields to synchronize

By default, AirtableSync calls #as_airtable_json on a record to get the fields that it needs to push to AirTable. #as_airtable_json simply calls #as_json in its default implementation. To change this behavior, you can override #as_airtable_json in your model:

# app/models/article.rb
class Article < ApplicationRecord
  include AirtableSync::RecordSync

  def as_airtable_json
    {
      'Post Title': self.title.capitalize,
      'Short Description': self.title.parameterize,
      'Long Description': self.created_at,
    }
  end
end

Sync a Rails model to different AirTable table

If AirTable table name does not match the Rails model collection name, you need to specify table name for each CreateRecordJob, DestroyRecordJob, and UpdateRecordJob call. If not specified, model collection name is used as the table name. You also need to replace included AirtableSync::RecordSync with custom callbacks that will call appropriate AirtableSync jobs.

For example:

AirtableSync::CreateRecordJob.perform_later(model_name, id, table_name)
AirtableSync::UpdateRecordJob.perform_later(model_name, id, table_name)
AirtableSync::DestroyRecordJob.perform_later(table_name:, airtable_id:)

Where:

  1. model_name - Rails model with airtable_id column
  2. table_name - AirTable table name (defaults to: model_name.underscore.pluralize.humanize)

For example:

AirtableSync::CreateRecordJob.perform_now('articles', 1, 'Stories')

Or, if you want to use the default 'Articles' table name:

AirtableSync::CreateRecordJob.perform_now('articles', 1) # table_name defaults to 'Articles'

Run the initial sync

After setting up which models you want to sync to AirTable, you can run the initial sync for each of the models:

AirtableSync::InitialSyncJob.perform_later('articles')

You can also run this from a Rake task:

bundle exec rails "airtable_sync:initial_sync[articles]"

Quotes are needed in order for this to work in all shells.

Important note

This gem silently "fails" (does nothing) when airtable_base_id or airtable_id is nil! This is not always desired behavior so be aware of that.

Contributing

PRs welcome!

To run RuboCop style check and RSpec tests run:

bundle exec rake

To run only RuboCop run:

bundle exec rails style

To run RSpec tests run:

bundle exec spec

License

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