tlaw 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +11 -0
- data/.yardopts +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +438 -0
- data/examples/demo_base.rb +10 -0
- data/examples/forecast_io.rb +113 -0
- data/examples/forecast_io_demo.rb +72 -0
- data/examples/open_weather_map.rb +266 -0
- data/examples/open_weather_map_demo.rb +219 -0
- data/examples/tmdb_demo.rb +133 -0
- data/examples/urbandictionary_demo.rb +105 -0
- data/lib/tlaw.rb +67 -0
- data/lib/tlaw/api.rb +58 -0
- data/lib/tlaw/api_path.rb +137 -0
- data/lib/tlaw/data_table.rb +116 -0
- data/lib/tlaw/dsl.rb +511 -0
- data/lib/tlaw/endpoint.rb +132 -0
- data/lib/tlaw/namespace.rb +159 -0
- data/lib/tlaw/param.rb +155 -0
- data/lib/tlaw/param/type.rb +113 -0
- data/lib/tlaw/param_set.rb +111 -0
- data/lib/tlaw/response_processor.rb +124 -0
- data/lib/tlaw/util.rb +45 -0
- data/lib/tlaw/version.rb +7 -0
- data/tlaw.gemspec +53 -0
- metadata +265 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6d841ff577a627eeecb9897b2cf4a20778eef17c
|
4
|
+
data.tar.gz: f52b898df817a0982b98d05000dc71f1e35cabb4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bbcbe2d3adbb328867b018d5664e2027191be9c47763ce8295bad2391a0ba9011af89fa073d920d016dc0f0ddf7f9c3fe60e1436458a88596658a6de93f6d28f
|
7
|
+
data.tar.gz: 63e85a71614104dff15bde2f9e188a16c8e72aadf3c037eeae06699e7ec9af612be73a2d5c1250fabccc31f8f1d159aa8f6ae1297cea13a04910c51868deb586
|
data/.codeclimate.yml
ADDED
data/.yardopts
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Victor 'zverok' Shepelev
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,438 @@
|
|
1
|
+
# TLAW - The Last API Wrapper
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/tlaw.svg)](http://badge.fury.io/rb/tlaw)
|
4
|
+
[![Build Status](https://travis-ci.org/molybdenum-99/tlaw.svg?branch=master)](https://travis-ci.org/molybdenum-99/tlaw)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/molybdenum-99/tlaw/badge.svg?branch=master)](https://coveralls.io/r/molybdenum-99/tlaw?branch=master)
|
6
|
+
|
7
|
+
**TLAW** (pronounce it like "tea+love"... or whatever) is the last (and
|
8
|
+
only) API wrapper framework for _get-only APIes_<sup>[*](#get-only-api)</sup>
|
9
|
+
(think weather, search, economical indicators, geonames and so on).
|
10
|
+
|
11
|
+
## Table Of Contents
|
12
|
+
|
13
|
+
* [Features](#features)
|
14
|
+
* [Why TLAW?](#why-tlaw)
|
15
|
+
* [Usage](#usage)
|
16
|
+
* [URLs and params description](#urls-and-params-description)
|
17
|
+
* [Response processing](#response-processing)
|
18
|
+
* [Flat hashes](#flat-hashes)
|
19
|
+
* [DataTable](#datatable)
|
20
|
+
* [Post-processing](#post-processing)
|
21
|
+
* [All at once](#all-at-once)
|
22
|
+
* [Documentability](#documentability)
|
23
|
+
* [Some demos](#some-demos)
|
24
|
+
* [Installation & compatibility](#installation-&-compatibility)
|
25
|
+
* [Upcoming features](#upcoming-features)
|
26
|
+
* [Get-only API](#get-only-api)
|
27
|
+
* [Current status](#current-status)
|
28
|
+
* [Links](#links)
|
29
|
+
* [Author](#author)
|
30
|
+
* [License](#license)
|
31
|
+
|
32
|
+
## Features
|
33
|
+
|
34
|
+
* **Pragmatic**: thorougly designed with tens of real world examples in mind,
|
35
|
+
not just your textbook's "perfect orthogonal REST API";
|
36
|
+
* **Opinionated**: goal is clean and logical Ruby libary, not just mechanical
|
37
|
+
1-by-1 endpoint-per-method wrapper for every fancy hivemind invention;
|
38
|
+
* **Easy and readable** definitions;
|
39
|
+
* **Discoverable**: once API defined in TLAW terms, you can easily investigate
|
40
|
+
it in runtime, obtain meaningful errors like "param `foo` is missing
|
41
|
+
while trying to access endpoint `bar`" and so on;
|
42
|
+
* **Sane metaprogramming**: allows to define entire branchy API wrapper with
|
43
|
+
tons of pathes and endpoints in really concise manner, while creating
|
44
|
+
_all_ corresponding classes/methods at definition time: so, at runtime
|
45
|
+
you have no 20-level dynamic dispatching, just your usual method calls
|
46
|
+
with clearly defined arguments and compact backtraces.
|
47
|
+
|
48
|
+
Take a look at our "model" OpenWeatherMap [wrapper](https://github.com/molybdenum-99/tlaw/blob/master/examples/open_weather_map.rb)
|
49
|
+
and [demo](https://github.com/molybdenum-99/tlaw/blob/master/examples/open_weather_map_demo.rb)
|
50
|
+
of its usage, showing how all those things work in reality.
|
51
|
+
|
52
|
+
## Why TLAW?
|
53
|
+
|
54
|
+
There are ton of small (and not-so-small) useful APIs about world around:
|
55
|
+
weather, movies, geographical features, dictionaries, world countries
|
56
|
+
statistics... Typically, when trying to use one of them from Ruby (or,
|
57
|
+
to be honest, from any programming language), you are stuck with two
|
58
|
+
options:
|
59
|
+
|
60
|
+
1. Study and use (or invent and build) some custom hand-made Wrapper
|
61
|
+
Library™ with ton of very custom design decisions (should responses
|
62
|
+
be just hashes, or [Hashie](https://github.com/intridea/hashie), or
|
63
|
+
real classes for each kind of response? What are the inputs? Where should
|
64
|
+
api key go, to global param?); or
|
65
|
+
2. Just "go commando" (sorry for the bad pun): construct URLs yourself,
|
66
|
+
parse responses yourself, control params (or ignore the control) yourself.
|
67
|
+
|
68
|
+
TLAW tries to close this gap: provide a base for _breath-easy_ API description
|
69
|
+
which produces solid, fast and reliable wrappers.
|
70
|
+
|
71
|
+
## Usage
|
72
|
+
|
73
|
+
### URLs and params description
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class Example < TLAW::API
|
77
|
+
base 'http://api.example.com'
|
78
|
+
|
79
|
+
param :api_key, required: true # this would be necessary for API instance creation
|
80
|
+
# So, the API instance would be e = Example.new(api_key: '123')
|
81
|
+
# ...and parameter ?api_key=123 would be added to any request
|
82
|
+
|
83
|
+
endpoint :foo # The simplest endpoint, will query "http://api.example.com/foo"
|
84
|
+
# And then you just do e.foo and obtain result
|
85
|
+
|
86
|
+
endpoint :bar, '/baz.json' # Path to query rewritten, will query "http://api.example.com/baz.json"
|
87
|
+
# Method is still e.bar, though.
|
88
|
+
|
89
|
+
# Now, for params definition:
|
90
|
+
endpont :movie do
|
91
|
+
param :id
|
92
|
+
end
|
93
|
+
# Method call would be movie(id: '123')
|
94
|
+
# Generated URL would be "http://api.example.com/movie?id=123"
|
95
|
+
|
96
|
+
# When param is part of the path, you can use RFC 6570
|
97
|
+
# URL template standard:
|
98
|
+
endpoint :movie, '/movies/{id}'
|
99
|
+
# That would generate method which is called like movie('123')
|
100
|
+
# ...and call to "http://api.example.com/movies/123"
|
101
|
+
|
102
|
+
# Now, we can stack endpoints in namespaces
|
103
|
+
namespace :foo do # adds /foo to path
|
104
|
+
namespace :bar, '/baz' do # optional path parameter works
|
105
|
+
endpoint :blah # URL for call would be "http://api.example.com/foo/baz/blah"
|
106
|
+
# And method call would be like e.foo.bar.blah(parameters)
|
107
|
+
end
|
108
|
+
|
109
|
+
# URL normalization works, so you can stack in namespaces even
|
110
|
+
# things not related to them in source API, "redesigning" API on
|
111
|
+
# the fly.
|
112
|
+
endpoint :books, '/../books.json' # Real URL would be "http://api.example.com/books"
|
113
|
+
# Yet method call is still namespaced like e.foo.books
|
114
|
+
end
|
115
|
+
|
116
|
+
# Namespaces can have their own input parameters
|
117
|
+
namespace :foo, '/foo/{id}' do
|
118
|
+
endpoint :bar # URL would be "http://api.example.com/foo/123/bar
|
119
|
+
# method call would be e.foo(123).bar
|
120
|
+
end
|
121
|
+
|
122
|
+
# ...and everything works in all possible and useful ways, just check
|
123
|
+
# docs and demos.
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
See [DSL module docs](http://www.rubydoc.info/gems/tlaw/TLAW/DSL) for
|
128
|
+
full description of all features (there are few, yet very powerful).
|
129
|
+
|
130
|
+
### Response processing
|
131
|
+
|
132
|
+
TLAW is really opinionated about response processing. Main things:
|
133
|
+
|
134
|
+
1. [Hashes are "flattened"](#flat-hashes);
|
135
|
+
2. [Arrays of hashes are converted to `DataTable`s](#datatable);
|
136
|
+
3. [Post-processors for fields are easily defined](#post-processing)
|
137
|
+
|
138
|
+
#### Flat hashes
|
139
|
+
|
140
|
+
The main (and usually top-level) answer of (JSON) API is a Hash/dictionary.
|
141
|
+
TLAW takes all multilevel hashes and make them flat.
|
142
|
+
|
143
|
+
Here is an example.
|
144
|
+
|
145
|
+
Source API responds like:
|
146
|
+
|
147
|
+
```json
|
148
|
+
{
|
149
|
+
"meta": {
|
150
|
+
"code": "OK",
|
151
|
+
},
|
152
|
+
"weahter": {
|
153
|
+
"temp": 10,
|
154
|
+
"precipation": 138
|
155
|
+
},
|
156
|
+
"location": {
|
157
|
+
"lat": 123,
|
158
|
+
"lon": 456
|
159
|
+
}
|
160
|
+
...
|
161
|
+
}
|
162
|
+
```
|
163
|
+
|
164
|
+
But TLAW response to `api.endpoint(params)` would return you a Hash looking
|
165
|
+
this way:
|
166
|
+
|
167
|
+
```json
|
168
|
+
{
|
169
|
+
"meta.code": "OK",
|
170
|
+
"weahter.temp": 10,
|
171
|
+
"weahter.precipation": 138,
|
172
|
+
"location.lat": 123,
|
173
|
+
"location.lon": 456
|
174
|
+
...
|
175
|
+
}
|
176
|
+
```
|
177
|
+
|
178
|
+
Reason? If you think of it and experiment with several examples, typically
|
179
|
+
with new & unexplored API you'll came up with code like:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
p response
|
183
|
+
# => 3 screens of VERY IMPORTANT RESPONSE
|
184
|
+
p response.class
|
185
|
+
# => Hash, ah, ok
|
186
|
+
p response.keys
|
187
|
+
# => ["meta", "weather", "location"], hmmm...
|
188
|
+
p response['weather']
|
189
|
+
# => stil 2.5 screens of unintelligible details
|
190
|
+
p response['weather'].class
|
191
|
+
# => Hash, ah!
|
192
|
+
p response['weather'].keys
|
193
|
+
# => and ad infinitum, real APIs are easily go 6-8 levels down
|
194
|
+
```
|
195
|
+
|
196
|
+
Now, with "opinionated" TLAW's flattening, for _any_ API you just do
|
197
|
+
the one and final `response.keys` and that's it: you see every available
|
198
|
+
data key, deep to the deepest depth.
|
199
|
+
|
200
|
+
> NB: probably, in the next versions TLAW will return some Hash descendant,
|
201
|
+
which would also still allow you to do `response['weather']` and receive
|
202
|
+
that "slice". Or it would not :) We are experimenting!
|
203
|
+
|
204
|
+
#### DataTable
|
205
|
+
|
206
|
+
The second main type of a (JSON) API answer, or of a part of an answer
|
207
|
+
is an array of homogenous hashes, like:
|
208
|
+
|
209
|
+
* list of data points (date - weather at that date);
|
210
|
+
* list of data objects (city id - city name - latitude - longitude);
|
211
|
+
* list of views to the data (climate model - projected temperature);
|
212
|
+
* and so on.
|
213
|
+
|
214
|
+
TLAW wraps this kind of data (array of homogenous hashes, or tables with
|
215
|
+
named columns) into `DataTable` structure, which you can think of as an
|
216
|
+
Excel spreadsheet (2d array with named columns), or loose DataFrame
|
217
|
+
pattern implementation (just like [daru](https://github.com/v0dro/daru)
|
218
|
+
or [pandas](http://pandas.pydata.org/), but seriously simpler—and much
|
219
|
+
more suited to the case).
|
220
|
+
|
221
|
+
Imagine you have an API responding something like:
|
222
|
+
|
223
|
+
```json
|
224
|
+
{
|
225
|
+
"meta": {"count": 20},
|
226
|
+
"data": [
|
227
|
+
{"date": "2016-09-01", "temp": 20, "humidity": 40},
|
228
|
+
{"date": "2016-09-02", "temp": 21, "humidity": 40},
|
229
|
+
{"date": "2016-09-03", "temp": 16, "humidity": 36},
|
230
|
+
...
|
231
|
+
]
|
232
|
+
}
|
233
|
+
```
|
234
|
+
|
235
|
+
With TLAW, you'll see this response this way:
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
pp response
|
239
|
+
{"meta.count"=>20,
|
240
|
+
"data"=>#<TLAW::DataTable[date, temp, humidity] x 20>}
|
241
|
+
# ^ That's all. Small and easy to grasp what is what. 3 named columns,
|
242
|
+
# 20 similar rows.
|
243
|
+
|
244
|
+
d = response['data']
|
245
|
+
# => #<TLAW::DataTable[date, temp, humidity] x 20>
|
246
|
+
|
247
|
+
d.count # Array-alike
|
248
|
+
# => 20
|
249
|
+
d.first
|
250
|
+
# => {"date" => "2016-09-01", "temp" => 20, "humidity" => 40}
|
251
|
+
|
252
|
+
d.keys # Hash-alike
|
253
|
+
# => ["date", "temp", "humidity"]
|
254
|
+
d["date"]
|
255
|
+
# => ["2016-09-01", "2016-09-02", "2016-09-03" ...
|
256
|
+
|
257
|
+
# And stuff:
|
258
|
+
d.to_h
|
259
|
+
# => {"date" => [...], "temp" => [...] ....
|
260
|
+
d.to_a
|
261
|
+
# => [{"date" => ..., "temp" => ..., "humidity" => ...}, {"date" => ...
|
262
|
+
|
263
|
+
d.columns('date', 'temp') # column-wise slice
|
264
|
+
# => #<TLAW::DataTable[date, temp] x 20>
|
265
|
+
d.columns('date', 'temp').first # and so on
|
266
|
+
# => {"date" => "2016-09-01", "temp" => 20}
|
267
|
+
```
|
268
|
+
|
269
|
+
Take a look at [DataTable docs](http://www.rubydoc.info/gems/tlaw/TLAW/DataTable)
|
270
|
+
and join designing it!
|
271
|
+
|
272
|
+
#### Post-processing
|
273
|
+
|
274
|
+
When you are not happy with result representation, you can post-process
|
275
|
+
them in several ways:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
# input is entire response, block can mutate it
|
279
|
+
post_process { |hash| hash['foo'] = 'bar' }
|
280
|
+
|
281
|
+
# input is entire response, and response is fully replaced with block's
|
282
|
+
# return value
|
283
|
+
post_process { |hash| hash['foo'] } # Now only "foo"s value will be response
|
284
|
+
|
285
|
+
# input is value of response's key "some_key", return value of a block
|
286
|
+
# becames new value of "some_key".
|
287
|
+
post_process('some_key') { |val| other_val }
|
288
|
+
|
289
|
+
# Post-processing each item, if response['foo'] is array:
|
290
|
+
post_process_items('foo') {
|
291
|
+
# mutate entire item
|
292
|
+
post_process { |item| item.delete('bar') }
|
293
|
+
|
294
|
+
# if item is a Hash, replace its "bar" value
|
295
|
+
post_process('bar') { |val| val.to_s }
|
296
|
+
}
|
297
|
+
|
298
|
+
# More realistic examples:
|
299
|
+
post_process('meta.count', &:to_i)
|
300
|
+
post_process('daily') {
|
301
|
+
post_process('date', &Date.method(:parse))
|
302
|
+
}
|
303
|
+
post_process('auxiliary_value') { nil } # Nil's will be thrown away completely
|
304
|
+
```
|
305
|
+
|
306
|
+
See full post-processing features descriptions in
|
307
|
+
[DSL module docs](http://www.rubydoc.info/gems/tlaw/TLAW/DSL).
|
308
|
+
|
309
|
+
#### All at once
|
310
|
+
|
311
|
+
All described response processing steps are performed in this order:
|
312
|
+
* parsing and initial flattening of JSON (or XML) hash;
|
313
|
+
* applying post-processors (and flatten the response after _each_ of
|
314
|
+
them);
|
315
|
+
* make `DataTable`s from arrays of hashes.
|
316
|
+
|
317
|
+
### Documentability
|
318
|
+
|
319
|
+
You do it this way:
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
class MyAPI < TLAW::API
|
323
|
+
desc %Q{
|
324
|
+
This is API, it works.
|
325
|
+
}
|
326
|
+
|
327
|
+
docs 'http://docs.example.com'
|
328
|
+
|
329
|
+
namespace :ns do
|
330
|
+
desc %Q{
|
331
|
+
It is some interesting thing.
|
332
|
+
}
|
333
|
+
|
334
|
+
docs 'http://docs.example.com/ns'
|
335
|
+
|
336
|
+
endpoint :baz do
|
337
|
+
desc %Q{
|
338
|
+
Should be useful.
|
339
|
+
}
|
340
|
+
|
341
|
+
docs 'http://docs.example.com/ns#baz'
|
342
|
+
|
343
|
+
param :param1,
|
344
|
+
desc: %Q{
|
345
|
+
You don't need it, really.
|
346
|
+
}
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
```
|
351
|
+
|
352
|
+
All of above is optional, but when provided, allows to investigate
|
353
|
+
things at runtime (in IRB/pry or test scripts). Again, look at
|
354
|
+
[OpenWeatherMap demo](https://github.com/molybdenum-99/tlaw/blob/master/examples/open_weather_map_demo.rb),
|
355
|
+
it shows how docs could be useful at runtime.
|
356
|
+
|
357
|
+
## Some demos
|
358
|
+
|
359
|
+
* Full-featured API wrappers:
|
360
|
+
* OpenWeatherMap: [source API docs](http://openweathermap.org/api),
|
361
|
+
[wrapper](https://github.com/molybdenum-99/tlaw/blob/master/examples/open_weather_map.rb),
|
362
|
+
extensively commented & explained
|
363
|
+
[demo code](https://github.com/molybdenum-99/tlaw/blob/master/examples/open_weather_map_demo.rb);
|
364
|
+
* ForecastIO: [API docs](https://developer.forecast.io/docs/v2),
|
365
|
+
[wrapper](https://github.com/molybdenum-99/tlaw/blob/master/examples/forecast_io.rb),
|
366
|
+
[demo code](https://github.com/molybdenum-99/tlaw/blob/master/examples/forecast_io_demo.rb);
|
367
|
+
* Demos of "fire-and-forget" wrappers:
|
368
|
+
* Urbandictionary's small and unofficial
|
369
|
+
[API wrapper](https://github.com/molybdenum-99/tlaw/blob/master/examples/urbandictionary_demo.rb);
|
370
|
+
* [Partial wrapper](https://github.com/molybdenum-99/tlaw/blob/master/examples/tmdb_demo.rb)
|
371
|
+
only for some features of large [TMDB API](docs.themoviedb.apiary.io/).
|
372
|
+
It also shows [on-the-fly updating](https://github.com/molybdenum-99/tlaw/blob/master/examples/tmdb_demo.rb#L85)
|
373
|
+
of already existing API wrapper to add some features.
|
374
|
+
|
375
|
+
## Installation & compatibility
|
376
|
+
|
377
|
+
Just `gem install tlaw` or add it to your `Gemfile`, nothing fancy.
|
378
|
+
|
379
|
+
Required Ruby version is 2.1+, JRuby works, Rubinius seems like not.
|
380
|
+
|
381
|
+
## Upcoming features
|
382
|
+
|
383
|
+
_(in no particular order)_
|
384
|
+
|
385
|
+
* [ ] Expose Faraday options (backends, request headers);
|
386
|
+
* [ ] Request-headers based auth;
|
387
|
+
* [ ] Responses caching;
|
388
|
+
* [ ] Response headers processing DSL;
|
389
|
+
* [ ] Paging support;
|
390
|
+
* [ ] Frequency-limited API support (requests counting);
|
391
|
+
* [ ] YARD docs generation for resulting wrappers;
|
392
|
+
* [ ] More solid wrapper demos (weather sites, geonames, worldbank);
|
393
|
+
* [ ] Approaches to testing generated wrappers (just good ol' VCR should
|
394
|
+
work, probably);
|
395
|
+
* [ ] Splat parameters.
|
396
|
+
|
397
|
+
## Get-only API
|
398
|
+
|
399
|
+
What is those "Get-only APIs" TLAW is suited for?
|
400
|
+
|
401
|
+
* It is only for _getting_ data, not changing them (though, API may use
|
402
|
+
HTTP POST requests in reality—for example, to transfer large request
|
403
|
+
objects);
|
404
|
+
* It would be cool if our weather APIs could allow things like
|
405
|
+
`POST /weather/kharkiv {sky: 'sunny', temp: '+21°C'}` in the middle
|
406
|
+
of December, huh? But we are not leaving in the world like this.
|
407
|
+
For now.
|
408
|
+
* It has utterly simple authentication protocol like "give us `api_key`
|
409
|
+
param in query" (though, TLAW plans to support more complex authentication);
|
410
|
+
* It typically returns JSON answers (though, TLAW supports XML via
|
411
|
+
awesome [crack](https://github.com/jnunemaker/crack)).
|
412
|
+
|
413
|
+
Alongside already mentioned examples (weather and so on), you can build
|
414
|
+
TLAW-backed "get-only" wrappers for bigger APIs (like Twitter), when
|
415
|
+
"gathering twits" is all you need. (Though, to be honest, TLAW's current
|
416
|
+
authorization abilities is far simpler than
|
417
|
+
[Twitter requirements](https://dev.twitter.com/oauth/application-only)).
|
418
|
+
|
419
|
+
## Current status
|
420
|
+
|
421
|
+
It is version 0.0.1. It is tested and documented, but not "tested in
|
422
|
+
battle", just invented. DSL is subject to be refined and validated,
|
423
|
+
everything could change (or broke suddenly). Tests are lot, though.
|
424
|
+
|
425
|
+
We plan to heavily utilize it for [reality](https://github.com/molybdenum-99/reality),
|
426
|
+
that would be serious evaluation of approaches and weeknesses.
|
427
|
+
|
428
|
+
## Links
|
429
|
+
|
430
|
+
* [API Docs](http://www.rubydoc.info/gems/tlaw)
|
431
|
+
|
432
|
+
## Author
|
433
|
+
|
434
|
+
[Victor Shepelev](http://zverok.github.io/)
|
435
|
+
|
436
|
+
## License
|
437
|
+
|
438
|
+
[MIT](./LICENSE.txt).
|