airtable2 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +23 -0
- data/README.md +95 -0
- data/Rakefile +9 -0
- data/airtable.gemspec +35 -0
- data/lib/airtable/base.rb +32 -0
- data/lib/airtable/client.rb +12 -0
- data/lib/airtable/error.rb +14 -0
- data/lib/airtable/record.rb +16 -0
- data/lib/airtable/resource.rb +19 -0
- data/lib/airtable/table.rb +62 -0
- data/lib/airtable/version.rb +6 -0
- data/lib/airtable.rb +14 -0
- data/test/airtable_test.rb +82 -0
- data/test/record_test.rb +23 -0
- data/test/test_helper.rb +15 -0
- metadata +218 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e76de7af1e8850fd762c839dcee996e5ce71e10c800548e991f80500da1c68d
|
4
|
+
data.tar.gz: 83ea6edb7e3a1473b1531f7dc3cee9273f6abdf2864e4c2bfa98051bd6667ea0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 651355e1f16d59ed0c96ba2088c65824bc97c707cc1cf2d34967a13a399abf6ff1e00bd424c38bc2ce5efc24bb47e0594c24b2e3ae606940cb3311a4c4da5b77
|
7
|
+
data.tar.gz: b5e46f6aee0d721703feaa4f615f819ac433a64d5dd625297d8d12479032dd7bf940684ab3027ef65bcdabd9d1175399ecc4ad758dabaa68155a201cdbc05435
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.vscode
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
24
|
+
.DS_Store
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2015 Nathan Esquenazi
|
2
|
+
Copyright (c) 2016 Airtable
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Airtable API Wrapper for Ruby
|
2
|
+
|
3
|
+
For when Airrecord is just too much.
|
4
|
+
|
5
|
+
# Note on library status
|
6
|
+
|
7
|
+
This is a fork of an abandoned [previous wrapper](https://github.com/nesquena/airtable-ruby). There's still plenty to do to get it up to speed with the current Airtable API.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'airtable2', github: 'https://github.com/aseroff/airtable-ruby', branch: 'main'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Creating a Client
|
22
|
+
|
23
|
+
First, be sure to register for an [airtable](https://airtable.com) account, setup a base, and create a token with the desired permissions for your base. Now, setup your Airtable client:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Pass in api key to client
|
27
|
+
@client = Airtable::Client.new('your.token.goes.here')
|
28
|
+
```
|
29
|
+
|
30
|
+
### Accessing Data
|
31
|
+
|
32
|
+
Now we can access our base
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
@base = @client.base('appExAmPlE')
|
36
|
+
```
|
37
|
+
|
38
|
+
and its tables
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
@tables = @base.tables
|
42
|
+
```
|
43
|
+
|
44
|
+
and create a new table
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
@table = @base.create_table({ name: 'Names', description: 'A list of names', fields: [{ name: 'name', type: 'singleLineText' }] })
|
48
|
+
```
|
49
|
+
|
50
|
+
### Manipulating Tables
|
51
|
+
|
52
|
+
You can update at a table's metadata with the `update` method:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
@table.update({ description: 'Updated description' })
|
56
|
+
```
|
57
|
+
|
58
|
+
### Querying Records
|
59
|
+
|
60
|
+
Once you have access to a table from above, we can query a set of records in the table with:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
@records = @table.records
|
64
|
+
```
|
65
|
+
|
66
|
+
### Inserting Records
|
67
|
+
|
68
|
+
A single record or an array of records can be inserted using the `add_records` method on a table (max 10 at a time):
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
@table.add_records({ 'Name': 'name value', 'Age': 35 })
|
72
|
+
```
|
73
|
+
|
74
|
+
### Deleting Records
|
75
|
+
|
76
|
+
A single record or an array of records can be destroyed by passing their ids to the `delete_records` method on a table:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
@record = @table.records[0]
|
80
|
+
@table.delete_records(@record.id)
|
81
|
+
```
|
82
|
+
|
83
|
+
Or as a convenience, you can delete all records with the `dump` method
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
@table.dump
|
87
|
+
```
|
88
|
+
|
89
|
+
## Contributing
|
90
|
+
|
91
|
+
1. Fork it ( https://github.com/aseroff/airtable-ruby/fork )
|
92
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
93
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
94
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
95
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/airtable.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'airtable/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'airtable2'
|
9
|
+
spec.version = Airtable::VERSION
|
10
|
+
spec.authors = ['Andrew Seroff', 'Nathan Esquenazi', 'Alexander Sorokin']
|
11
|
+
spec.email = ['andy@seroff.co']
|
12
|
+
spec.summary = 'Easily connect to airtable data using ruby'
|
13
|
+
spec.description = 'Easily connect to airtable data using ruby with access to all of the airtable features.'
|
14
|
+
spec.homepage = 'https://github.com/aseroff/airtable-ruby'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 3.1'
|
22
|
+
spec.add_dependency 'activesupport'
|
23
|
+
spec.add_dependency 'httparty'
|
24
|
+
spec.add_dependency 'json'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler'
|
27
|
+
spec.add_development_dependency 'minitest'
|
28
|
+
spec.add_development_dependency 'rake'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'rubocop-md'
|
31
|
+
spec.add_development_dependency 'rubocop-minitest'
|
32
|
+
spec.add_development_dependency 'rubocop-performance'
|
33
|
+
spec.add_development_dependency 'webmock'
|
34
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Object corresponding to an Airtable Base
|
4
|
+
class Airtable::Base < Airtable::Resource
|
5
|
+
def initialize(token, id)
|
6
|
+
@token = token
|
7
|
+
@id = id
|
8
|
+
self.class.headers({ 'Authorization': "Bearer #{@token}", 'Content-Type': 'application/json' })
|
9
|
+
end
|
10
|
+
|
11
|
+
# Expects {name:,description:,fields:[]}
|
12
|
+
def create_table(table_data)
|
13
|
+
response = self.class.post("#{base_url}/tables",
|
14
|
+
body: table_data.to_json).parsed_response
|
15
|
+
|
16
|
+
check_and_raise_error(response)
|
17
|
+
|
18
|
+
Airtable::Table.new @token, @id, response
|
19
|
+
end
|
20
|
+
|
21
|
+
def tables
|
22
|
+
response = self.class.get("#{base_url}/tables")
|
23
|
+
|
24
|
+
check_and_raise_error(response)
|
25
|
+
|
26
|
+
response['tables'].map { Airtable::Table.new(@token, @id, _1) }
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def base_url = "/v0/meta/bases/#{@id}"
|
32
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Error class
|
4
|
+
class Airtable::Error < StandardError
|
5
|
+
attr_reader :message, :type
|
6
|
+
|
7
|
+
# {"error"=>{"type"=>"UNKNOWN_COLUMN_NAME", "message"=>"Could not find fields foo"}}
|
8
|
+
|
9
|
+
def initialize(error_hash)
|
10
|
+
@message = error_hash['message']
|
11
|
+
@type = error_hash['type']
|
12
|
+
super(@message)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Object corresponding to an Airtable Record
|
4
|
+
class Airtable::Record < Airtable::Resource
|
5
|
+
attr_reader :fields
|
6
|
+
|
7
|
+
def initialize(token, base_id, table_id, api_response)
|
8
|
+
@token = token
|
9
|
+
@base_id = base_id
|
10
|
+
@table_id = table_id
|
11
|
+
api_response.deep_symbolize_keys.each do |key, value|
|
12
|
+
instance_variable_set(:"@#{key}", value)
|
13
|
+
end
|
14
|
+
self.class.headers({ 'Authorization': "Bearer #{@token}", 'Content-Type': 'application/json' })
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Base class for authorized resources sending network requests
|
4
|
+
class Airtable::Resource
|
5
|
+
include HTTParty
|
6
|
+
base_uri 'https://api.airtable.com'
|
7
|
+
# debug_output $stdout
|
8
|
+
|
9
|
+
attr_reader :id, :token
|
10
|
+
|
11
|
+
def initialize(token)
|
12
|
+
@token = token
|
13
|
+
self.class.headers({ 'Authorization': "Bearer #{@token}", 'Content-Type': 'application/json' })
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_and_raise_error(response)
|
17
|
+
response['error'] ? raise(Error, response['error']) : false
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Object corresponding to an Airtable Table
|
4
|
+
class Airtable::Table < Airtable::Resource
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(token, base_id, api_response)
|
8
|
+
@token = token
|
9
|
+
@base_id = base_id
|
10
|
+
api_response.deep_symbolize_keys.each do |key, value|
|
11
|
+
instance_variable_set(:"@#{key}", value)
|
12
|
+
end
|
13
|
+
self.class.headers({ 'Authorization': "Bearer #{@token}", 'Content-Type': 'application/json' })
|
14
|
+
end
|
15
|
+
|
16
|
+
def records
|
17
|
+
response = self.class.get(table_url)
|
18
|
+
|
19
|
+
check_and_raise_error(response)
|
20
|
+
|
21
|
+
response['records'].map { Airtable::Record.new(@token, @base_id, @table_id, _1) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def update(table_data)
|
25
|
+
response = self.class.patch("/v0/meta/bases/#{@base_id}/tables/#{@id}",
|
26
|
+
body: table_data.to_json).parsed_response
|
27
|
+
|
28
|
+
check_and_raise_error(response)
|
29
|
+
|
30
|
+
Airtable::Table.new @token, @base_id, response
|
31
|
+
end
|
32
|
+
|
33
|
+
# limit 10 records
|
34
|
+
def add_records(records)
|
35
|
+
response = self.class.post(table_url,
|
36
|
+
body: { records: Array(records).map { |fields| { fields: } } }.to_json).parsed_response
|
37
|
+
|
38
|
+
check_and_raise_error(response)
|
39
|
+
|
40
|
+
response['records'].map { Airtable::Record.new(@token, @base_id, @id, _1) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_records(record_ids)
|
44
|
+
params = Array(record_ids).compact.map { "records[]=#{_1}" }.join('&')
|
45
|
+
response = self.class.delete("#{table_url}?#{params}").parsed_response
|
46
|
+
|
47
|
+
check_and_raise_error(response)
|
48
|
+
|
49
|
+
record_ids
|
50
|
+
end
|
51
|
+
|
52
|
+
def dump
|
53
|
+
records.map(&:id).each_slice(10) do |record_id_set|
|
54
|
+
delete_records(record_id_set)
|
55
|
+
sleep(0.2)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def table_url = "/v0/#{@base_id}/#{@id}"
|
62
|
+
end
|
data/lib/airtable.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'delegate'
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
require 'airtable/version'
|
9
|
+
require 'airtable/resource'
|
10
|
+
require 'airtable/record'
|
11
|
+
require 'airtable/table'
|
12
|
+
require 'airtable/base'
|
13
|
+
require 'airtable/client'
|
14
|
+
require 'airtable/error'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Airtable do
|
6
|
+
before do
|
7
|
+
@client_key = '12345'
|
8
|
+
@app_key = 'appXXV84Qu'
|
9
|
+
@sheet_name = 'Test'
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'with Airtable' do
|
13
|
+
it 'should allow client to be created' do
|
14
|
+
@client = Airtable::Client.new(@client_key)
|
15
|
+
|
16
|
+
assert_kind_of Airtable::Client, @client
|
17
|
+
@table = @client.table(@app_key, @sheet_name)
|
18
|
+
|
19
|
+
assert_kind_of Airtable::Table, @table
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should fetch record set' do
|
23
|
+
stub_airtable_response!("https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}",
|
24
|
+
{ 'records' => [], 'offset' => 'abcde' })
|
25
|
+
@table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
26
|
+
@records = @table.records
|
27
|
+
|
28
|
+
assert_equal 'abcde', @records.offset
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should select records based on a formula' do
|
32
|
+
query_str = "OR(RECORD_ID() = 'recXYZ1', RECORD_ID() = 'recXYZ2', RECORD_ID() = 'recXYZ3', RECORD_ID() = 'recXYZ4')"
|
33
|
+
escaped_query = HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER.call(filterByFormula: query_str)
|
34
|
+
request_url = "https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}?#{escaped_query}"
|
35
|
+
stub_airtable_response!(request_url, { 'records' => [] })
|
36
|
+
@table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
37
|
+
@select_records = @table.select(formula: query_str)
|
38
|
+
|
39
|
+
assert_empty @select_records.records
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should raise an ArgumentError if a formula is not a string' do
|
43
|
+
stub_airtable_response!("https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}",
|
44
|
+
{ 'records' => [], 'offset' => 'abcde' })
|
45
|
+
@table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
46
|
+
_ { proc { @table.select(formula: { foo: 'bar' }) } }.must_raise ArgumentError
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should allow creating records' do
|
50
|
+
stub_airtable_response!("https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}",
|
51
|
+
{ 'fields' => { 'name' => 'Sarah Jaine', 'email' => 'sarah@jaine.com', 'foo' => 'bar' }, 'id' => '12345' }, :post)
|
52
|
+
table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
53
|
+
record = Airtable::Record.new(name: 'Sarah Jaine', email: 'sarah@jaine.com')
|
54
|
+
table.create(record)
|
55
|
+
|
56
|
+
assert_equal '12345', record['id']
|
57
|
+
assert_equal 'bar', record['foo']
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should allow updating records' do
|
61
|
+
record_id = '12345'
|
62
|
+
stub_airtable_response!("https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}/#{record_id}",
|
63
|
+
{ 'fields' => { 'name' => 'Sarah Jaine', 'email' => 'sarah@jaine.com', 'foo' => 'bar' }, 'id' => record_id }, :put)
|
64
|
+
table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
65
|
+
record = Airtable::Record.new(name: 'Sarah Jaine', email: 'sarah@jaine.com', id: record_id)
|
66
|
+
table.update(record)
|
67
|
+
|
68
|
+
assert_equal '12345', record['id']
|
69
|
+
assert_equal 'bar', record['foo']
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should raise an error when the API returns an error' do
|
73
|
+
stub_airtable_response!("https://api.airtable.com/v0/#{@app_key}/#{@sheet_name}",
|
74
|
+
{ 'error' => { 'type' => 'UNKNOWN_COLUMN_NAME', 'message' => 'Could not find fields foo' } }, :post, 422)
|
75
|
+
table = Airtable::Client.new(@client_key).table(@app_key, @sheet_name)
|
76
|
+
record = Airtable::Record.new(foo: 'bar')
|
77
|
+
assert_raises Airtable::Error do
|
78
|
+
table.create(record)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/test/record_test.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Airtable do
|
6
|
+
describe Airtable::Record do
|
7
|
+
it 'should not return id in fields_for_update' do
|
8
|
+
record = Airtable::Record.new(name: 'Sarah Jaine', email: 'sarah@jaine.com', id: 12_345)
|
9
|
+
_(record.fields_for_update).wont_include(:id)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns new columns in fields_for_update' do
|
13
|
+
record = Airtable::Record.new(name: 'Sarah Jaine', email: 'sarah@jaine.com', id: 12_345)
|
14
|
+
record[:website] = 'http://sarahjaine.com'
|
15
|
+
_(record.fields_for_update).must_include(:website)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns fields_for_update in original capitalization' do
|
19
|
+
record = Airtable::Record.new('Name' => 'Sarah Jaine')
|
20
|
+
_(record.fields_for_update).must_include('Name')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'airtable'
|
4
|
+
require 'webmock/minitest'
|
5
|
+
require 'minitest/pride'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
|
8
|
+
def stub_airtable_response!(url, response, method = :get, status = 200)
|
9
|
+
stub_request(method, url)
|
10
|
+
.to_return(
|
11
|
+
body: response.to_json,
|
12
|
+
status: status,
|
13
|
+
headers: { 'Content-Type' => 'application/json' }
|
14
|
+
)
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: airtable2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Seroff
|
8
|
+
- Nathan Esquenazi
|
9
|
+
- Alexander Sorokin
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2024-10-26 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: httparty
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: json
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: bundler
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: minitest
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rake
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: rubocop
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rubocop-md
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: rubocop-minitest
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: rubocop-performance
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
type: :development
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: webmock
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
type: :development
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
description: Easily connect to airtable data using ruby with access to all of the
|
170
|
+
airtable features.
|
171
|
+
email:
|
172
|
+
- andy@seroff.co
|
173
|
+
executables: []
|
174
|
+
extensions: []
|
175
|
+
extra_rdoc_files: []
|
176
|
+
files:
|
177
|
+
- ".gitignore"
|
178
|
+
- Gemfile
|
179
|
+
- LICENSE.txt
|
180
|
+
- README.md
|
181
|
+
- Rakefile
|
182
|
+
- airtable.gemspec
|
183
|
+
- lib/airtable.rb
|
184
|
+
- lib/airtable/base.rb
|
185
|
+
- lib/airtable/client.rb
|
186
|
+
- lib/airtable/error.rb
|
187
|
+
- lib/airtable/record.rb
|
188
|
+
- lib/airtable/resource.rb
|
189
|
+
- lib/airtable/table.rb
|
190
|
+
- lib/airtable/version.rb
|
191
|
+
- test/airtable_test.rb
|
192
|
+
- test/record_test.rb
|
193
|
+
- test/test_helper.rb
|
194
|
+
homepage: https://github.com/aseroff/airtable-ruby
|
195
|
+
licenses:
|
196
|
+
- MIT
|
197
|
+
metadata:
|
198
|
+
rubygems_mfa_required: 'true'
|
199
|
+
post_install_message:
|
200
|
+
rdoc_options: []
|
201
|
+
require_paths:
|
202
|
+
- lib
|
203
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - ">="
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '3.1'
|
208
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
|
+
requirements:
|
210
|
+
- - ">="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: '0'
|
213
|
+
requirements: []
|
214
|
+
rubygems_version: 3.5.21
|
215
|
+
signing_key:
|
216
|
+
specification_version: 4
|
217
|
+
summary: Easily connect to airtable data using ruby
|
218
|
+
test_files: []
|