airrecord 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cb016c7f7bfa6d6e5affe3432faedf8cebf92a2
4
- data.tar.gz: eff4bdb0fb4d85cbeaf2ca1dcf82f9c5523e6050
3
+ metadata.gz: 6488c3737cb574a3e1e5e1cbc1d5ae665482c364
4
+ data.tar.gz: 8ebba576595589c7d8e9c6558d9e2032d6953507
5
5
  SHA512:
6
- metadata.gz: f2d60c1447b99e57037782bdd36ec9b93a058b5d0d713b10a8646cc41285d94ca4ccdced574d048b8c720c910fd4beeb020905e110df432b2f0062444e965f75
7
- data.tar.gz: 3055b1ad8dd62efd1a28b07d11ace7e06b0411f082021f3ac6c5da7e1d0f986d84ca08874e2fcd8e217de21f1eec8025034216dc2e91739ee6fff73a418b4438
6
+ metadata.gz: 16a9ffc9fc7ec8a69061e7b26041410c3fcdba2bd2bb1b21f3034cc9f3f60a88dd0b8370118ed167595ba3e4a7aa51780987e74d6176d737736989c0c966fbb4
7
+ data.tar.gz: 998c84a7691409db02f09bb65479e7ebfe1e9a33b820dec3da333083751f4ca0031e892708e438dc63097bf4b39847c5b4143ccb631d3ed70ec76742996319a4
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  vendor/
11
11
  test/fixtures
12
12
  .byebug_history
13
+ *.gem
data/.travis.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2.3
5
- before_install: gem install bundler -v 1.12.5
4
+ - 2.3.3
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2017 Simon Eskildsen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md CHANGED
@@ -9,6 +9,11 @@ inviting inspiration from ActiveRecord's API.
9
9
  gem 'airrecord'
10
10
  ```
11
11
 
12
+ This library is provided to enforce a mental model of a database, as described
13
+ in [this post](http://sirupsen.com/minimum-viable-airtable/). Furthermore as an
14
+ alternative to the [official
15
+ library](https://github.com/airtable/airtable-ruby).
16
+
12
17
  ## Examples
13
18
 
14
19
  There's a simple API that allows more ad-hoc querying of Airtable:
@@ -70,3 +75,10 @@ tea = Tea.find(tea.id)
70
75
  puts tea[:hot_brews].first[:rating]
71
76
  # => "3 - Fine"
72
77
  ```
78
+
79
+ ## Contributing
80
+
81
+ Contributions will be happily accepted in the form of Github Pull Requests!
82
+
83
+ * Please ensure CI is passing before submitting your pull request for review.
84
+ * Please provide tests that fail without your change.
@@ -1,3 +1,3 @@
1
1
  module Airrecord
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airrecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Eskildsen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-21 00:00:00.000000000 Z
11
+ date: 2017-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -103,8 +103,8 @@ extra_rdoc_files: []
103
103
  files:
104
104
  - ".gitignore"
105
105
  - ".travis.yml"
106
- - ":w"
107
106
  - Gemfile
107
+ - LICENSE
108
108
  - README.md
109
109
  - Rakefile
110
110
  - airrecord.gemspec
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  version: '0'
132
132
  requirements: []
133
133
  rubyforge_project:
134
- rubygems_version: 2.4.5.1
134
+ rubygems_version: 2.6.10
135
135
  signing_key:
136
136
  specification_version: 4
137
137
  summary: Airtable client
data/:w DELETED
@@ -1,341 +0,0 @@
1
- require 'securerandom'
2
- require 'test_helper'
3
-
4
- class AirtableTest < Minitest::Test
5
- def setup
6
- @table = Airtable.table("key6Zk9xjvoRQG1FO", "appxIxY6d7lz4yHZG", "table1")
7
-
8
- @stubs = Faraday::Adapter::Test::Stubs.new
9
- @table.client.connection = Faraday.new { |builder|
10
- builder.adapter :test, @stubs
11
- }
12
-
13
- stub_request([{"Name": "omg", "Notes": "hello world", " Something else\n" => "hi"}, {"Name": "more", "Notes": "walrus"}])
14
- end
15
-
16
- def test_retrieve_records
17
- assert_instance_of Array, @table.records
18
- end
19
-
20
- def test_filter_records
21
- stub_request([{"Name": "yes"}, {"Name": "no"}])
22
-
23
- records = @table.records(filter: "Name")
24
- assert_equal "yes", records[0][:name]
25
- end
26
-
27
- def test_sort_records
28
- stub_request([{"Name": "a"}, {"Name": "b"}])
29
-
30
- records = @table.records(sort: { Name: 'asc' })
31
- assert_equal "a", records[0][:name]
32
- assert_equal "b", records[1][:name]
33
- end
34
-
35
- def test_view_records
36
- stub_request([{"Name": "a"}, {"Name": "a"}])
37
-
38
- records = @table.records(view: 'A')
39
- assert_equal "a", records[0][:name]
40
- assert_equal "a", records[1][:name]
41
- end
42
-
43
- def test_follow_pagination_by_default
44
- stub_request([{"Name": "1"}, {"Name": "2"}], offset: 'dasfuhiu')
45
- stub_request([{"Name": "3"}, {"Name": "4"}], offset: 'odjafio', clear: false)
46
- stub_request([{"Name": "5"}, {"Name": "6"}], clear: false)
47
-
48
- records = @table.records
49
- assert_equal 6, records.size
50
- end
51
-
52
- def test_dont_follow_pagination_if_disabled
53
- stub_request([{"Name": "1"}, {"Name": "2"}], offset: 'dasfuhiu')
54
- stub_request([{"Name": "3"}, {"Name": "4"}], offset: 'odjafio', clear: false)
55
- stub_request([{"Name": "5"}, {"Name": "6"}], clear: false)
56
-
57
- records = @table.records(paginate: false)
58
- assert_equal 2, records.size
59
- end
60
-
61
- def test_index_by_normalized_name
62
- assert_equal "omg", first_record[:name]
63
- end
64
-
65
- def test_index_by_column_name
66
- assert_equal "omg", first_record["Name"]
67
- end
68
-
69
- def test_cleans_bad_keys
70
- assert_equal "hi", first_record[:something_else]
71
- end
72
-
73
- def test_id
74
- assert_instance_of String, first_record.id
75
- end
76
-
77
- def test_created_at
78
- assert_instance_of Time, first_record.created_at
79
- end
80
-
81
- def test_error_response
82
- stub_error_request(type: "TABLE_NOT_FOUND", message: "Could not find table", table: "unknown")
83
-
84
- assert_raises Airtable::Error do
85
- Airtable.table("key6Zk9xjvoRQG1FO", "appxIxY6d7lz4yHZG", "unknown").records
86
- end
87
- end
88
-
89
- def test_change_value
90
- record = first_record
91
- record[:name] = "testest"
92
- assert_equal "testest", record[:name]
93
- end
94
-
95
- def test_change_value_on_column_name
96
- record = first_record
97
- record["Name"] = "testest"
98
- assert_equal "testest", record[:name]
99
- end
100
-
101
- def test_change_value_and_update
102
- record = first_record
103
-
104
- record[:name] = "new_name"
105
- stub_patch_request(record, ["Name"])
106
-
107
- assert record.save
108
- end
109
-
110
- def test_change_value_then_save_again_should_noop
111
- record = first_record
112
-
113
- record[:name] = "new_name"
114
- stub_patch_request(record, ["Name"])
115
-
116
- assert record.save
117
- assert record.save
118
- end
119
-
120
- def test_updates_fields_to_newest_values_after_update
121
- record = first_record
122
-
123
- record[:name] = "new_name"
124
- stub_patch_request(record, ["Name"], return_body: record.fields.merge("Notes" => "new animal"))
125
-
126
- assert record.save
127
- assert_equal "new_name", record[:name]
128
- assert_equal "new animal", record[:notes]
129
- end
130
-
131
- def test_update_failure
132
- record = first_record
133
-
134
- record[:name] = "new_name"
135
- stub_patch_request(record, ["Name"], return_body: { error: { type: "oh noes", message: 'yes' } }, status: 401)
136
-
137
- assert_raises Airtable::Error do
138
- record.save
139
- end
140
- end
141
-
142
- def test_update_failure_then_succeed
143
- record = first_record
144
-
145
- record[:name] = "new_name"
146
- stub_patch_request(record, ["Name"], return_body: { error: { type: "oh noes", message: 'yes' } }, status: 401)
147
-
148
- assert_raises Airtable::Error do
149
- record.save
150
- end
151
-
152
- stub_patch_request(record, ["Name"])
153
- assert record.save
154
- end
155
-
156
- def test_update_raises_if_new_record
157
- record = @table.build_record(Name: "omg")
158
-
159
- assert_raises Airtable::Error do
160
- record.save
161
- end
162
- end
163
-
164
- def test_existing_record_is_not_new
165
- refute first_record.new_record?
166
- end
167
-
168
- def test_build_new_record
169
- record = @table.build_record(Name: "omg")
170
-
171
- refute record.id
172
- refute record.created_at
173
- assert record.new_record?
174
- end
175
-
176
- def test_create_new_record
177
- record = @table.build_record(Name: "omg")
178
-
179
- stub_post_request(record)
180
-
181
- assert record.create
182
- end
183
-
184
- def test_create_existing_record_fails
185
- record = @table.build_record(Name: "omg")
186
-
187
- stub_post_request(record)
188
-
189
- assert record.create
190
-
191
- assert_raises Airtable::Error do
192
- record.create
193
- end
194
- end
195
-
196
- def test_create_handles_error
197
- record = @table.build_record(Name: "omg")
198
-
199
- stub_post_request(record, status: 401, return_body: { error: { type: "omg", message: "wow" }})
200
-
201
- assert_raises Airtable::Error do
202
- record.create
203
- end
204
- end
205
-
206
- def test_find
207
- record = @table.build_record(Name: "walrus")
208
-
209
- stub_find_request(record, id: "iodfajsofja")
210
-
211
- record = @table.find("iodfajsofja")
212
- assert_equal "walrus", record[:name]
213
- end
214
-
215
- def test_find_handles_error
216
- stub_find_request(nil, return_body: { error: { type: "not found", message: "not found" } }, id: "noep", status: 404)
217
-
218
- assert_raises Airtable::Error do
219
- @table.find("noep")
220
- end
221
- end
222
-
223
- def test_destroy_new_record_fails
224
- record = @table.build_record(Name: "walrus")
225
-
226
- assert_raises Airtable::Error do
227
- record.destroy
228
- end
229
- end
230
-
231
- def test_destroy_record
232
- record = first_record
233
- stub_delete_request(record.id)
234
- assert record.destroy
235
- end
236
-
237
- def test_fail_destroy_record
238
- record = first_record
239
- stub_delete_request(record.id, status: 404, response_body: { error: { type: "not found", message: "whatever" } }.to_json)
240
-
241
- assert_raises Airtable::Error do
242
- record.destroy
243
- end
244
- end
245
-
246
- def test_error_handles_errors_without_body
247
- record = first_record
248
-
249
- stub_delete_request(record.id, status: 500)
250
-
251
- assert_raises Airtable::Error do
252
- record.destroy
253
- end
254
- end
255
-
256
- private
257
-
258
- def first_record
259
- @table.records.first
260
- end
261
-
262
- def stub_delete_request(id, table: @table, status: 202, response_body: "")
263
- @stubs.delete("/v0/#{@table.base_key}/#{@table.table_name}/#{id}") do |env|
264
- [status, {}, response_body]
265
- end
266
- end
267
-
268
- def stub_post_request(record, table: @table, status: 200, headers: {}, return_body: nil)
269
- return_body ||= {
270
- id: SecureRandom.hex(16),
271
- fields: record.fields,
272
- createdTime: Time.now,
273
- }
274
- return_body = return_body.to_json
275
-
276
- request_body = { fields: record.fields }.to_json
277
-
278
- @stubs.post("/v0/#{@table.base_key}/#{@table.table_name}", request_body) do |env|
279
- [status, headers, return_body]
280
- end
281
- end
282
-
283
- def stub_patch_request(record, updated_keys, table: @table1, status: 200, headers: {}, return_body: nil)
284
- return_body ||= record.fields
285
- return_body = return_body.to_json
286
-
287
- request_body = {
288
- fields: Hash[updated_keys.map { |key|
289
- [key, record.fields[key]]
290
- }]
291
- }.to_json
292
-
293
- @stubs.patch("/v0/#{@table.base_key}/#{@table.table_name}/#{record.id}", request_body) do |env|
294
- [status, headers, return_body]
295
- end
296
- end
297
-
298
- # TODO: Problem, can't stub on params.
299
- def stub_request(records, table: @table, status: 200, headers: {}, offset: nil, clear: true)
300
- @stubs.instance_variable_set(:@stack, {}) if clear
301
-
302
- body = {
303
- records: records.map { |record|
304
- {
305
- id: SecureRandom.hex(16),
306
- fields: record,
307
- createdTime: Time.now,
308
- }
309
- },
310
- offset: offset,
311
- }.to_json
312
-
313
- @stubs.get("/v0/#{@table.base_key}/#{@table.table_name}") do |env|
314
- [status, headers, body]
315
- end
316
- end
317
-
318
- def stub_find_request(record = nil, table: @table, status: 200, headers: {}, return_body: nil, id: nil)
319
- return_body ||= record.fields
320
- return_body = return_body.to_json
321
-
322
- id ||= record.id
323
-
324
- @stubs.get("/v0/#{@table.base_key}/#{@table.table_name}/#{id}") do |env|
325
- [status, headers, return_body]
326
- end
327
- end
328
-
329
- def stub_error_request(type:, message:, status: 401, headers: {}, table: @table)
330
- body = {
331
- error: {
332
- type: type,
333
- message: message,
334
- }
335
- }.to_json
336
-
337
- @stubs.get("/v0/#{@table.base_key}/#{@table.table_name}") do |env|
338
- [status, headers, body]
339
- end
340
- end
341
- end