norairrecord 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +23 -1
- data/lib/norairrecord/client.rb +1 -0
- data/lib/norairrecord/table.rb +50 -9
- data/lib/norairrecord/version.rb +1 -1
- data/lib/norairrecord.rb +2 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5f9d1c3992d715d55a1308918a574a00b83042da2e58bfbcc9389ff51e0b6cd
|
4
|
+
data.tar.gz: d4372b35b219e5ffd6384c42e3687dd9019dabbb48d8bb622d395eb8aadab90a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fdcca5fc8ee492d692fe1271d60052d82ddf4c18ff4ec275e464cf9871dd52cf9996e393ac01292bc780a31dc0681c92af1485282e6b11138fea35957ae1b18
|
7
|
+
data.tar.gz: f023f648cb134d4de8c0773fd1a2d0882393ea7109af105f2cd9b23fde4d1eeb9d519ee695ac341912a191d3d6a3b6b946efb3d7c8bc6d60ecdaf387dacfcef5
|
data/README.md
CHANGED
@@ -29,4 +29,26 @@ stuff not in the OG:
|
|
29
29
|
* custom UA
|
30
30
|
* `Norairrecord.user_agent = "i'm the reason why you're getting 429s!"`
|
31
31
|
* `Table#airtable_url`
|
32
|
-
* what it says on the tin!
|
32
|
+
* what it says on the tin!
|
33
|
+
* `Table.has_subtypes`
|
34
|
+
* hokay so:
|
35
|
+
* ```ruby
|
36
|
+
class Friend < Norairrecord::Table
|
37
|
+
# base_key/table_name, etc...
|
38
|
+
has_subtypes "type", { # based on 'type' column...
|
39
|
+
"person" => "Person", # when 'person' instantiate record as Person
|
40
|
+
"shark" => "Shark"
|
41
|
+
}, strict: true # if strict, unmapped types will raise UnknownTypeError
|
42
|
+
# otherwise they will be instantiated as the base class
|
43
|
+
end
|
44
|
+
|
45
|
+
class Person < Friend; end
|
46
|
+
class Shark < Friend; end
|
47
|
+
|
48
|
+
Friend.all
|
49
|
+
=> [<Person>, <Person>, <Shark>]
|
50
|
+
```
|
51
|
+
* `Norairrecord::RecordNotFoundError`
|
52
|
+
* never again wonder if an error is because you goofed up an ID or you're getting ratelimited
|
53
|
+
* `where` argument on `has_many` lookups
|
54
|
+
* `Table#first`, `Table#first_where`
|
data/lib/norairrecord/client.rb
CHANGED
data/lib/norairrecord/table.rb
CHANGED
@@ -3,8 +3,15 @@ require 'rubygems' # For Gem::Version
|
|
3
3
|
module Norairrecord
|
4
4
|
class Table
|
5
5
|
class << self
|
6
|
-
|
7
|
-
|
6
|
+
attr_writer :api_key, :base_key, :table_name
|
7
|
+
|
8
|
+
def base_key
|
9
|
+
@base_key || (superclass < Table ? superclass.base_key : nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def table_name
|
13
|
+
@table_name || (superclass < Table ? superclass.table_name : nil)
|
14
|
+
end
|
8
15
|
|
9
16
|
def client
|
10
17
|
@@clients ||= {}
|
@@ -16,12 +23,12 @@ module Norairrecord
|
|
16
23
|
end
|
17
24
|
|
18
25
|
def has_many(method_name, options)
|
19
|
-
define_method(method_name.to_sym) do
|
26
|
+
define_method(method_name.to_sym) do |where: nil, sort: nil|
|
20
27
|
# Get association ids in reverse order, because Airtable's UI and API
|
21
28
|
# sort associations in opposite directions. We want to match the UI.
|
22
29
|
ids = (self[options.fetch(:column)] || []).reverse
|
23
30
|
table = Kernel.const_get(options.fetch(:class))
|
24
|
-
return table.find_many(ids) unless options[:single]
|
31
|
+
return table.find_many(ids, sort:, where:) unless options[:single]
|
25
32
|
|
26
33
|
(id = ids.first) ? table.find(id) : nil
|
27
34
|
end
|
@@ -37,23 +44,30 @@ module Norairrecord
|
|
37
44
|
|
38
45
|
alias has_one belongs_to
|
39
46
|
|
47
|
+
def has_subtypes(column, mapping, strict: false)
|
48
|
+
@subtype_column = column
|
49
|
+
@subtype_mapping = mapping
|
50
|
+
@subtype_strict = strict
|
51
|
+
end
|
52
|
+
|
40
53
|
def find(id)
|
41
54
|
response = client.connection.get("v0/#{base_key}/#{client.escape(table_name)}/#{id}")
|
42
55
|
parsed_response = client.parse(response.body)
|
43
56
|
|
44
57
|
if response.success?
|
45
|
-
self.
|
58
|
+
self.new_with_subtype(parsed_response["fields"], id: id, created_at: parsed_response["createdTime"])
|
46
59
|
else
|
47
60
|
client.handle_error(response.status, parsed_response)
|
48
61
|
end
|
49
62
|
end
|
50
63
|
|
51
|
-
def find_many(ids)
|
64
|
+
def find_many(ids, where: nil, sort: nil)
|
52
65
|
return [] if ids.empty?
|
53
66
|
|
54
67
|
or_args = ids.map { |id| "RECORD_ID() = '#{id}'"}.join(',')
|
55
68
|
formula = "OR(#{or_args})"
|
56
|
-
|
69
|
+
formula = "AND(#{formula},#{where})" if where
|
70
|
+
records(filter: formula, sort:).sort_by { |record| or_args.index(record.id) }
|
57
71
|
end
|
58
72
|
|
59
73
|
def update(id, update_hash = {}, options = {})
|
@@ -78,6 +92,18 @@ module Norairrecord
|
|
78
92
|
new(fields).tap { |record| record.save(options) }
|
79
93
|
end
|
80
94
|
|
95
|
+
def new_with_subtype(fields, id:, created_at:)
|
96
|
+
if @subtype_column
|
97
|
+
clazz = self
|
98
|
+
st = @subtype_mapping[fields[@subtype_column]]
|
99
|
+
raise Norairrecord::UnknownTypeError, "#{fields[@subtype_column]}?????" if @subtype_strict && st.nil?
|
100
|
+
clazz = Kernel.const_get(st) if st
|
101
|
+
clazz.new(fields, id:, created_at:)
|
102
|
+
else
|
103
|
+
self.new(fields, id: id, created_at: created_at)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
81
107
|
def records(filter: nil, sort: nil, view: nil, offset: nil, paginate: true, fields: nil, max_records: nil, page_size: nil)
|
82
108
|
options = {}
|
83
109
|
options[:filterByFormula] = filter if filter
|
@@ -100,8 +126,8 @@ module Norairrecord
|
|
100
126
|
|
101
127
|
if response.success?
|
102
128
|
records = parsed_response["records"]
|
103
|
-
records
|
104
|
-
self.
|
129
|
+
records.map! { |record|
|
130
|
+
self.new_with_subtype(record["fields"], id: record["id"], created_at: record["createdTime"])
|
105
131
|
}
|
106
132
|
|
107
133
|
if paginate && parsed_response["offset"]
|
@@ -122,9 +148,24 @@ module Norairrecord
|
|
122
148
|
client.handle_error(response.status, parsed_response)
|
123
149
|
end
|
124
150
|
end
|
151
|
+
|
152
|
+
def first(options = {})
|
153
|
+
records(**options.merge(max_records: 1)).first
|
154
|
+
end
|
155
|
+
|
156
|
+
def first_where(filter, options = {})
|
157
|
+
first(options.merge(filter:))
|
158
|
+
end
|
159
|
+
|
160
|
+
def where(filter, options = {})
|
161
|
+
records(**options.merge(filter:))
|
162
|
+
end
|
163
|
+
|
125
164
|
alias all records
|
126
165
|
end
|
127
166
|
|
167
|
+
|
168
|
+
|
128
169
|
attr_reader :fields, :id, :created_at, :updated_keys
|
129
170
|
|
130
171
|
# This is an awkward definition for Ruby 3 to remain backwards compatible.
|
data/lib/norairrecord/version.rb
CHANGED
data/lib/norairrecord.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: norairrecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nora
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -113,7 +113,7 @@ homepage: https://github.com/24c02/norairrecord
|
|
113
113
|
licenses:
|
114
114
|
- MIT
|
115
115
|
metadata: {}
|
116
|
-
post_install_message:
|
116
|
+
post_install_message:
|
117
117
|
rdoc_options: []
|
118
118
|
require_paths:
|
119
119
|
- lib
|
@@ -129,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
129
|
version: '0'
|
130
130
|
requirements: []
|
131
131
|
rubygems_version: 3.5.16
|
132
|
-
signing_key:
|
132
|
+
signing_key:
|
133
133
|
specification_version: 4
|
134
134
|
summary: Airtable client
|
135
135
|
test_files: []
|