A Rails pattern for calling external APIs, then storing and processing their responses.
Add this line to your application's Gemfile:
gem "active_operator"And then execute:
bundle install
rails generate active_operator:install
rails db:migrateGenerate an operation class by running rails generate active_operator:operation [name].
class Geocoding::V1 < ApplicationOperation
def request
# Make API call and return response, which will be stored in the operation record
faraday.get(
"https://api.geocod.io/v1.8/geocode",
{
q: record.address,
api_key: Rails.application.credentials.dig(:geocodio, :api_key),
fields: "timezone"
}
)
end
def process
# Load the response stored in the operation record, and update perform updates and other actions
result = response.dig("body", "results", 0)
record.update!(
latitude: result.dig("location", "lat"),
longitude: result.dig("location", "lng"),
timezone: result.dig("fields", "timezone", "name")
)
end
endUse the has_operation method in your models:
class Location < ApplicationRecord
has_operation :geocoding, class_name: "Geocoding::V1"
endYou are responsible for saving the associated operation record.
# Save an associated operation for a new record, within a transaction
location = Location.new(location_params)
location.build_geocoding
location.save
# Save an associated operation for an existing record
location = Location.find(params[:id])
location.geocoding.save# Synchronous execution
location = Location.find(params[:id])
location.geocoding.perform
# Asynchronous execution
location = Location.find(params[:id])
location.geocoding.perform_laterlocation.geocoding.received? # Operation completed request and stored response
location.geocoding.processed? # Operation completed processing of response
location.geocoding.errored? # Operation failed either request or processAfter checking out the repo, run bin/setup to install dependencies. Then, run bin/test to run the tests.
Bug reports and pull requests are welcome on GitHub at https://github.com/jeremysmithco/active_operator.