Add support for Airtable
This commit is contained in:
36
lib/spreadsheet_backends/airtable.rb
Normal file
36
lib/spreadsheet_backends/airtable.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'airrecord'
|
||||
module SpreadsheetBackends
|
||||
class Airtable
|
||||
|
||||
attr_accessor :form, :user
|
||||
|
||||
def initialize(form)
|
||||
@form = form
|
||||
@user = form.user
|
||||
end
|
||||
|
||||
def url
|
||||
"https://airtable.com/#{form.airtable_app_key}"
|
||||
end
|
||||
|
||||
def append(data)
|
||||
result = table.create(data, typecast: true)
|
||||
result.id.present?
|
||||
rescue Airrecord::Error => e
|
||||
return false
|
||||
end
|
||||
|
||||
def create
|
||||
# Airtable must already exist
|
||||
# TODO: maybe add validation here?
|
||||
end
|
||||
|
||||
def headers
|
||||
table.records.first&.fields&.keys # we only know the headers once we have at least one record
|
||||
end
|
||||
|
||||
def table
|
||||
@table ||= Airrecord.table(form.airtable_api_key, form.airtable_app_key, form.airtable_table)
|
||||
end
|
||||
end
|
||||
end
|
||||
71
lib/spreadsheet_backends/google_sheets.rb
Normal file
71
lib/spreadsheet_backends/google_sheets.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
require 'google/apis/sheets_v4'
|
||||
module SpreadsheetBackends
|
||||
class GoogleSheets
|
||||
# Hash to translate an index to a A1 notation. e.g. 1 => 'B', 27 => 'AA'
|
||||
COLUMN_INDEX_TO_LETTER = Hash.new {|hash,key| hash[key] = hash[key - 1].next }.merge({0 => "A"})
|
||||
|
||||
attr_accessor :form, :user
|
||||
|
||||
def initialize(form)
|
||||
@form = form
|
||||
@user = form.user
|
||||
end
|
||||
|
||||
def url
|
||||
"https://docs.google.com/spreadsheets/d/#{form.google_spreadsheet_id}/edit" if form.google_spreadsheet_id.present?
|
||||
end
|
||||
|
||||
def append(data)
|
||||
data = data.with_indifferent_access
|
||||
check_spreadsheed_headers!(data)
|
||||
|
||||
values = headers.map { |key| data[key] }
|
||||
range = "A1:A#{COLUMN_INDEX_TO_LETTER[values.length]}1"
|
||||
value_range = Google::Apis::SheetsV4::ValueRange.new(values: [values], major_dimension: 'ROWS')
|
||||
|
||||
result = spreadsheet_service.append_spreadsheet_value(form.google_spreadsheet_id, range, value_range, value_input_option: 'USER_ENTERED')
|
||||
result.updates.updated_rows > 0
|
||||
end
|
||||
|
||||
def create
|
||||
sheets = Google::Apis::SheetsV4::SheetsService.new
|
||||
sheets.authorization = user.google_authorization
|
||||
create_object = Google::Apis::SheetsV4::Spreadsheet.new(properties: { title: form.title})
|
||||
spreadsheet = sheets.create_spreadsheet(create_object)
|
||||
form.update(google_spreadsheet_id: spreadsheet.spreadsheet_id)
|
||||
end
|
||||
|
||||
def headers
|
||||
@headers ||= begin
|
||||
values = spreadsheet_service.get_spreadsheet_values(form.google_spreadsheet_id, 'A1:An').values
|
||||
# if there are no headers yet, return an empty array
|
||||
if values
|
||||
values[0].map(&:strip)
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def spreadsheet_service
|
||||
@spreadsheet_service ||= Google::Apis::SheetsV4::SheetsService.new.tap do |s|
|
||||
s.authorization = user.google_authorization
|
||||
end
|
||||
end
|
||||
|
||||
def check_spreadsheed_headers!(data)
|
||||
missing_headers = data.keys.map { |k| k.to_s.strip } - headers
|
||||
append_missing_headers(missing_headers) unless missing_headers.empty?
|
||||
end
|
||||
|
||||
def append_missing_headers(missing_headers)
|
||||
start_column = COLUMN_INDEX_TO_LETTER[headers.length]
|
||||
end_column = COLUMN_INDEX_TO_LETTER[headers.length + missing_headers.length]
|
||||
range = "#{start_column}1:#{end_column}1"
|
||||
value_range = Google::Apis::SheetsV4::ValueRange.new(values: [missing_headers], major_dimension: 'ROWS')
|
||||
spreadsheet_service.update_spreadsheet_value(form.google_spreadsheet_id, range, value_range, value_input_option: 'USER_ENTERED')
|
||||
@headers = nil # reset header values to refresh memoization on next access
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user