leif 0.0.4 → 0.0.5
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 +22 -0
- data/bin/leif +9 -317
- data/leif.gemspec +1 -0
- data/lib/leif/cli.rb +203 -0
- data/lib/leif/collection_json.rb +70 -0
- data/lib/leif/section.rb +26 -0
- data/lib/leif/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ea567a178df95bf78d96ecd8785fdc0efe759bc
|
4
|
+
data.tar.gz: a28cad7fb674260307e5e582f8b13a245cb0d814
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bb6da4ca06176c47e46c2a8647efac6d8af5eff9e4b44aa799d94a16e6b958966a490adc33ae1072b7a03a6d1b0e5a5eba0f3c139ec232dfcb607be6ec3df48
|
7
|
+
data.tar.gz: ca287bcfc08378281846e479c30e2cb07a5430de571bfcfd50fcd4d55d85550009dc33ebf477b96c9be5761ed849a9e337f5d2e6da3c4b863fa8ff7e65d07aa6
|
data/README.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
A hypermedia browser for the CloudApp Collection+JSON API.
|
4
4
|
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
`leif` requires Ruby 1.9.3 or greater. Windows is not yet supported. If you're
|
8
|
+
willing to lend a hand, we'd love to officially support it.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
``` bash
|
13
|
+
$ gem install leif
|
14
|
+
$ leif
|
15
|
+
```
|
16
|
+
|
17
|
+
`leif` includes a man page. To read it:
|
18
|
+
|
19
|
+
``` bash
|
20
|
+
$ gem install gem-man
|
21
|
+
$ gem man leif
|
22
|
+
```
|
23
|
+
|
5
24
|
## Interactive Commands
|
6
25
|
|
7
26
|
- `root`:
|
@@ -17,6 +36,9 @@ A hypermedia browser for the CloudApp Collection+JSON API.
|
|
17
36
|
- `token` <u>token</u>:
|
18
37
|
Authenticate using the given token and reload the current resource.
|
19
38
|
|
39
|
+
- `help`:
|
40
|
+
Print interactive command help.
|
41
|
+
|
20
42
|
## Example
|
21
43
|
|
22
44
|
The UI is weak at this point and not very intuitive. To get started, here's a
|
data/bin/leif
CHANGED
@@ -1,325 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'leif/cli'
|
3
|
+
require 'leif/collection_json'
|
4
|
+
require 'leif/section'
|
2
5
|
|
3
|
-
|
4
|
-
extend Forwardable
|
5
|
-
|
6
|
-
def_delegators :collection, :href, :links, :link, :items,
|
7
|
-
:template, :fill_template_field, :fill_template, :submit_template
|
8
|
-
|
9
|
-
def collection
|
10
|
-
@collection ||= Collection.new(body)
|
11
|
-
end
|
12
|
-
|
13
|
-
class Collection < SimpleDelegator
|
14
|
-
def initialize(body)
|
15
|
-
super body.fetch('collection')
|
16
|
-
end
|
17
|
-
|
18
|
-
def href
|
19
|
-
fetch('href')
|
20
|
-
end
|
21
|
-
|
22
|
-
def links
|
23
|
-
return [] unless has_key?('links')
|
24
|
-
fetch('links').map {|link| Link.new(link) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def link(relation)
|
28
|
-
links.find {|link| link.relation == relation }
|
29
|
-
end
|
30
|
-
|
31
|
-
def template
|
32
|
-
@template ||= Item.new(fetch('template'))
|
33
|
-
end
|
34
|
-
|
35
|
-
def fill_template_field(name, value)
|
36
|
-
template[name] = value
|
37
|
-
end
|
38
|
-
|
39
|
-
def fill_template(item)
|
40
|
-
item.to_hash.each do |name, value|
|
41
|
-
p [name, value]
|
42
|
-
fill_template_field name, value
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def items
|
47
|
-
return [] unless has_key?('items')
|
48
|
-
fetch('items').map {|item| Item.new(item) }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class Link
|
53
|
-
attr_accessor :relation, :href
|
54
|
-
|
55
|
-
def initialize(link)
|
56
|
-
@relation = link.fetch('rel')
|
57
|
-
@href = link.fetch('href')
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class Item
|
62
|
-
attr_accessor :item
|
63
|
-
|
64
|
-
def initialize(item)
|
65
|
-
@item = item
|
66
|
-
end
|
67
|
-
|
68
|
-
def href
|
69
|
-
@item.fetch('href')
|
70
|
-
end
|
71
|
-
|
72
|
-
def data
|
73
|
-
@item.fetch('data')
|
74
|
-
end
|
75
|
-
|
76
|
-
def []=(name, value)
|
77
|
-
datum = data.find {|datum| datum['name'] == name }
|
78
|
-
return unless datum
|
79
|
-
datum['value'] = value
|
80
|
-
end
|
81
|
-
|
82
|
-
def to_hash
|
83
|
-
data.each_with_object({}) do |datum, data|
|
84
|
-
data[datum['name']] = datum['value']
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def conn
|
91
|
-
@conn ||= Faraday.new(url: 'https://api.getcloudapp.com') do |config|
|
92
|
-
config.request :url_encoded
|
93
|
-
config.response :logger, logger
|
94
|
-
config.response :json, :content_type => /\bjson$/
|
95
|
-
config.adapter Faraday.default_adapter
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def logger
|
100
|
-
@logger ||= Logger.new(debug_output)
|
101
|
-
end
|
102
|
-
|
103
|
-
def debug_output
|
104
|
-
@debug_output ||= StringIO.new
|
105
|
-
end
|
106
|
-
|
107
|
-
def reset_debug_output
|
108
|
-
debug_output.rewind
|
109
|
-
debug_output.truncate 0
|
110
|
-
end
|
111
|
-
|
112
|
-
def make_request(uri, data = {}, method = :unset)
|
113
|
-
method = data.empty? ? :get : :post if method == :unset
|
114
|
-
reset_debug_output
|
115
|
-
@response = CollectionJsonResponse.new(conn.send(method, uri, data))
|
116
|
-
end
|
117
|
-
|
118
|
-
def get_root
|
119
|
-
make_request '/'
|
120
|
-
end
|
121
|
-
|
122
|
-
def retry_request
|
123
|
-
make_request @response.env[:url].request_uri
|
124
|
-
end
|
125
|
-
|
126
|
-
def section(banner)
|
6
|
+
trap('INT') do
|
127
7
|
puts
|
128
|
-
|
129
|
-
output = Output.new(1)
|
130
|
-
yield output
|
131
|
-
output.print '[empty]' if output.empty?
|
8
|
+
exit
|
132
9
|
end
|
133
10
|
|
134
|
-
|
135
|
-
|
136
|
-
def empty?() @empty end
|
137
|
-
|
138
|
-
def initialize(level, io = $stdout)
|
139
|
-
@level = level
|
140
|
-
@io = io
|
141
|
-
@empty = true
|
142
|
-
end
|
143
|
-
|
144
|
-
def print(line = '')
|
145
|
-
print_lines Array(line)
|
146
|
-
end
|
147
|
-
|
148
|
-
def print_lines(lines)
|
149
|
-
@empty = false
|
150
|
-
lines.each do |line|
|
151
|
-
io.puts(indentation + line)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def indentation
|
156
|
-
' ' * level
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def print_response
|
161
|
-
section 'Request' do |out|
|
162
|
-
out.print "#{@response.env[:method].upcase} #{@response.env[:url]}"
|
163
|
-
out.print_lines @response.env[:request_headers].map {|header, value|
|
164
|
-
"#{header}: #{value}"
|
165
|
-
}
|
166
|
-
end
|
167
|
-
|
168
|
-
section 'Response' do |out|
|
169
|
-
out.print_lines @response.headers.map {|header, value|
|
170
|
-
"#{header}: #{value}"
|
171
|
-
}
|
172
|
-
end
|
173
|
-
|
174
|
-
section 'Body' do |out|
|
175
|
-
out.print_lines JSON.pretty_generate(@response.body).lines
|
176
|
-
end
|
177
|
-
|
178
|
-
section 'Links' do |out|
|
179
|
-
out.print link_relations unless link_relations.empty?
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def link_relations
|
184
|
-
@response.links.map(&:relation).join(', ')
|
185
|
-
end
|
186
|
-
|
187
|
-
def request_basic_authentication(username = :ask, password = :ask)
|
188
|
-
username = ask('Username: ') if username == :ask
|
189
|
-
password = ask('Password: ') {|q| q.echo = '*' } if password == :ask
|
190
|
-
conn.basic_auth username, password
|
191
|
-
retry_request
|
192
|
-
end
|
193
|
-
|
194
|
-
def request_token_authentication(token = '2x033S09401z300E')
|
195
|
-
conn.headers['Authorization'] = "Token token=#{token.inspect}"
|
196
|
-
retry_request
|
197
|
-
end
|
198
|
-
|
199
|
-
def follow_link(relation = :ask)
|
200
|
-
relation = ask('Relation: ') if relation == :ask
|
201
|
-
make_request @response.link(relation).href
|
202
|
-
end
|
203
|
-
|
204
|
-
def create_item
|
205
|
-
loop do
|
206
|
-
section 'Create Item' do |out|
|
207
|
-
out.print_lines JSON.pretty_generate(@response.template.item).lines
|
208
|
-
end
|
209
|
-
|
210
|
-
puts
|
211
|
-
puts 'Fill the template to create a new item.'
|
212
|
-
name = ask('Name (empty to submit): ')
|
213
|
-
break if name.empty?
|
214
|
-
value = ask('Value: ')
|
215
|
-
|
216
|
-
@response.fill_template_field name, value
|
217
|
-
end
|
218
|
-
|
219
|
-
make_request @response.collection.href, @response.template.to_hash
|
220
|
-
end
|
221
|
-
|
222
|
-
def update_item
|
223
|
-
item = @response.collection.items.find do |item|
|
224
|
-
section 'Item' do |out|
|
225
|
-
out.print_lines JSON.pretty_generate(item.item).lines
|
226
|
-
end
|
227
|
-
|
228
|
-
puts
|
229
|
-
response = ask('Select this item to update [y,n]? ') do |q|
|
230
|
-
q.character = true
|
231
|
-
q.validate = /\A[yn]\Z/
|
232
|
-
end
|
233
|
-
|
234
|
-
response == 'y'
|
235
|
-
end
|
236
|
-
|
237
|
-
@response.fill_template item
|
238
|
-
|
11
|
+
Leif::Cli.new.tap do |cli|
|
12
|
+
cli.get_root
|
239
13
|
loop do
|
240
|
-
|
241
|
-
|
242
|
-
end
|
243
|
-
|
244
|
-
puts
|
245
|
-
puts 'Fill the template to update the item.'
|
246
|
-
name = ask('Name (empty to submit): ')
|
247
|
-
break if name.empty?
|
248
|
-
value = ask('Value: ')
|
249
|
-
|
250
|
-
@response.fill_template_field name, value
|
14
|
+
cli.print_response
|
15
|
+
cli.get_next_action
|
251
16
|
end
|
252
|
-
|
253
|
-
make_request item.href, @response.template.to_hash, :put
|
254
17
|
end
|
255
|
-
|
256
|
-
def print_debug
|
257
|
-
section 'Debug' do |out|
|
258
|
-
debug_output.rewind
|
259
|
-
out.print_lines debug_output.readlines
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def print_help
|
264
|
-
puts <<EOS
|
265
|
-
root:
|
266
|
-
Go back to the root
|
267
|
-
|
268
|
-
follow <rel>:
|
269
|
-
Follow link with the given relation.
|
270
|
-
|
271
|
-
template [<name>=<value>...]:
|
272
|
-
Fill the template with the given name/value pairs and submit.
|
273
|
-
|
274
|
-
basic [<username> [<password>]]:
|
275
|
-
Authenticate with HTTP Basic and reload the current resource. Will be
|
276
|
-
prompted for username and password if omitted.
|
277
|
-
|
278
|
-
token <token>:
|
279
|
-
Authenticate using the given token and reload the current resource.
|
280
|
-
|
281
|
-
debug:
|
282
|
-
Print debug output from the previous HTTP request and response.
|
283
|
-
EOS
|
284
|
-
end
|
285
|
-
|
286
|
-
def get_next_action
|
287
|
-
command, args = ask_for_action
|
288
|
-
case command
|
289
|
-
when 'r', 'root' then get_root
|
290
|
-
when 'f', 'follow' then follow_link(*args)
|
291
|
-
when 'create' then create_item
|
292
|
-
when 'update' then update_item
|
293
|
-
when 'b', 'basic' then request_basic_authentication(*args)
|
294
|
-
when 't', 'token' then request_token_authentication(*args)
|
295
|
-
when 'd', 'debug' then print_debug; get_next_action
|
296
|
-
when '?', 'help' then print_help; get_next_action
|
297
|
-
when 'q', 'quit' then exit
|
298
|
-
else puts 'Try again.'; get_next_action
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def ask_for_action
|
303
|
-
puts
|
304
|
-
input = ask('> ') {|q| q.readline = true }.split(/\s/)
|
305
|
-
[ input.first, input[1..-1] ]
|
306
|
-
end
|
307
|
-
|
308
|
-
trap('INT') { puts; exit }
|
309
|
-
|
310
|
-
get_root
|
311
|
-
loop do
|
312
|
-
print_response
|
313
|
-
get_next_action
|
314
|
-
end
|
315
|
-
|
316
|
-
BEGIN {
|
317
|
-
require 'delegate'
|
318
|
-
require 'forwardable'
|
319
|
-
require 'highline/import'
|
320
|
-
require 'json'
|
321
|
-
require 'faraday'
|
322
|
-
require 'faraday_middleware'
|
323
|
-
require 'logger'
|
324
|
-
require 'stringio'
|
325
|
-
}
|
data/leif.gemspec
CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.add_dependency 'faraday', '~> 0.8.8'
|
16
16
|
spec.add_dependency 'faraday_middleware', '~> 0.9.0'
|
17
17
|
spec.add_dependency 'highline', '~> 1.6.19'
|
18
|
+
spec.add_development_dependency 'rspec'
|
18
19
|
spec.add_development_dependency 'ronn'
|
19
20
|
|
20
21
|
spec.bindir = 'bin'
|
data/lib/leif/cli.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'highline/import'
|
4
|
+
require 'json'
|
5
|
+
require 'logger'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
module Leif
|
9
|
+
class Cli
|
10
|
+
def conn
|
11
|
+
@conn ||= Faraday.new(url: 'https://api.getcloudapp.com') do |config|
|
12
|
+
config.request :url_encoded
|
13
|
+
config.response :logger, logger
|
14
|
+
config.response :json, :content_type => /\bjson$/
|
15
|
+
config.adapter Faraday.default_adapter
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger
|
20
|
+
@logger ||= Logger.new(debug_output)
|
21
|
+
end
|
22
|
+
|
23
|
+
def debug_output
|
24
|
+
@debug_output ||= StringIO.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def banner(banner, &message)
|
28
|
+
puts
|
29
|
+
Section.banner(banner, &message)
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset_debug_output
|
33
|
+
debug_output.rewind
|
34
|
+
debug_output.truncate 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_request(uri, data = {}, method = :unset)
|
38
|
+
method = data.empty? ? :get : :post if method == :unset
|
39
|
+
reset_debug_output
|
40
|
+
@response = conn.send(method, uri, data)
|
41
|
+
end
|
42
|
+
|
43
|
+
def collection
|
44
|
+
Leif::CollectionJson::Collection.new(@response.body)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_root
|
48
|
+
make_request '/'
|
49
|
+
end
|
50
|
+
|
51
|
+
def retry_request
|
52
|
+
make_request @response.env[:url].request_uri
|
53
|
+
end
|
54
|
+
|
55
|
+
def print_response
|
56
|
+
banner 'Request' do |out|
|
57
|
+
out.print "#{@response.env[:method].upcase} #{@response.env[:url]}"
|
58
|
+
out.print @response.env[:request_headers].map {|header, value|
|
59
|
+
"#{header}: #{value}"
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
banner 'Response' do |out|
|
64
|
+
out.print @response.headers.map {|header, value|
|
65
|
+
"#{header}: #{value}"
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
banner 'Body' do |out|
|
70
|
+
out.print JSON.pretty_generate(@response.body).lines
|
71
|
+
end
|
72
|
+
|
73
|
+
banner 'Links' do |out|
|
74
|
+
unless collection.link_relations.empty?
|
75
|
+
out.print collection.link_relations.join(', ')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def request_basic_authentication(username = :ask, password = :ask)
|
81
|
+
username = ask('Username: ') if username == :ask
|
82
|
+
password = ask('Password: ') {|q| q.echo = '*' } if password == :ask
|
83
|
+
conn.basic_auth username, password
|
84
|
+
retry_request
|
85
|
+
end
|
86
|
+
|
87
|
+
def request_token_authentication(token = '2x033S09401z300E')
|
88
|
+
conn.headers['Authorization'] = "Token token=#{token.inspect}"
|
89
|
+
retry_request
|
90
|
+
end
|
91
|
+
|
92
|
+
def follow_link(relation = :ask)
|
93
|
+
relation = ask('Relation: ') if relation == :ask
|
94
|
+
make_request collection.link_href(relation)
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_item
|
98
|
+
template = collection.template
|
99
|
+
|
100
|
+
loop do
|
101
|
+
banner 'Create Item' do |out|
|
102
|
+
out.print JSON.pretty_generate(template).lines
|
103
|
+
end
|
104
|
+
|
105
|
+
puts
|
106
|
+
puts 'Fill the template to create a new item.'
|
107
|
+
name = ask('Name (empty to submit): ')
|
108
|
+
break if name.empty?
|
109
|
+
value = ask('Value: ')
|
110
|
+
|
111
|
+
template = template.fill_field name, value
|
112
|
+
end
|
113
|
+
|
114
|
+
make_request template.href, template.convert_to_json, template.method
|
115
|
+
end
|
116
|
+
|
117
|
+
def update_item
|
118
|
+
item = collection.items.find do |item|
|
119
|
+
banner 'Item' do |out|
|
120
|
+
out.print JSON.pretty_generate(item).lines
|
121
|
+
end
|
122
|
+
|
123
|
+
puts
|
124
|
+
response = ask('Select this item to update [y,n]? ') do |q|
|
125
|
+
q.character = true
|
126
|
+
q.validate = /\A[yn]\Z/
|
127
|
+
end
|
128
|
+
|
129
|
+
response == 'y'
|
130
|
+
end
|
131
|
+
|
132
|
+
template = collection.item_template item
|
133
|
+
|
134
|
+
loop do
|
135
|
+
banner 'Update Item' do |out|
|
136
|
+
out.print JSON.pretty_generate(template).lines
|
137
|
+
end
|
138
|
+
|
139
|
+
puts
|
140
|
+
puts 'Fill the template to update the item.'
|
141
|
+
name = ask('Name (empty to submit): ')
|
142
|
+
break if name.empty?
|
143
|
+
value = ask('Value: ')
|
144
|
+
|
145
|
+
template = template.fill_field name, value
|
146
|
+
end
|
147
|
+
|
148
|
+
make_request template.href, template.convert_to_json, template.method
|
149
|
+
end
|
150
|
+
|
151
|
+
def print_debug
|
152
|
+
banner 'Debug' do |out|
|
153
|
+
debug_output.rewind
|
154
|
+
out.print debug_output.readlines
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def print_help
|
159
|
+
puts <<EOS
|
160
|
+
root:
|
161
|
+
Go back to the root
|
162
|
+
|
163
|
+
follow <rel>:
|
164
|
+
Follow link with the given relation.
|
165
|
+
|
166
|
+
template [<name>=<value>...]:
|
167
|
+
Fill the template with the given name/value pairs and submit.
|
168
|
+
|
169
|
+
basic [<username> [<password>]]:
|
170
|
+
Authenticate with HTTP Basic and reload the current resource. Will be
|
171
|
+
prompted for username and password if omitted.
|
172
|
+
|
173
|
+
token <token>:
|
174
|
+
Authenticate using the given token and reload the current resource.
|
175
|
+
|
176
|
+
debug:
|
177
|
+
Print debug output from the previous HTTP request and response.
|
178
|
+
EOS
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_next_action
|
182
|
+
command, args = ask_for_action
|
183
|
+
case command
|
184
|
+
when 'r', 'root' then get_root
|
185
|
+
when 'f', 'follow' then follow_link(*args)
|
186
|
+
when 'create' then create_item
|
187
|
+
when 'update' then update_item
|
188
|
+
when 'b', 'basic' then request_basic_authentication(*args)
|
189
|
+
when 't', 'token' then request_token_authentication(*args)
|
190
|
+
when 'd', 'debug' then print_debug; get_next_action
|
191
|
+
when '?', 'help' then print_help; get_next_action
|
192
|
+
when 'q', 'quit' then exit
|
193
|
+
else puts 'Try again.'; get_next_action
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def ask_for_action
|
198
|
+
puts
|
199
|
+
input = ask('> ') {|q| q.readline = true }.split(/\s/)
|
200
|
+
[ input.first, input[1..-1] ]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Leif
|
5
|
+
module CollectionJson
|
6
|
+
class Collection
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@data, :fetch, :has_key?
|
9
|
+
|
10
|
+
def initialize(body)
|
11
|
+
@data = body.fetch('collection')
|
12
|
+
end
|
13
|
+
|
14
|
+
def link_href(relation)
|
15
|
+
links.find {|link| link.fetch('rel') == relation }.fetch('href')
|
16
|
+
end
|
17
|
+
|
18
|
+
def link_relations
|
19
|
+
links.map {|link| link.fetch('rel') }
|
20
|
+
end
|
21
|
+
|
22
|
+
def links
|
23
|
+
return [] unless has_key?('links')
|
24
|
+
fetch('links')
|
25
|
+
end
|
26
|
+
|
27
|
+
def items
|
28
|
+
return [] unless has_key?('items')
|
29
|
+
fetch('items')
|
30
|
+
end
|
31
|
+
|
32
|
+
def template(href = fetch('href'), method = :post)
|
33
|
+
Template.new(fetch('template'), href, method)
|
34
|
+
end
|
35
|
+
|
36
|
+
def item_template(item)
|
37
|
+
template = template(item.fetch('href'), :put)
|
38
|
+
item.fetch('data').inject(template) {|template, datum|
|
39
|
+
template.fill_field datum.fetch('name'), datum.fetch('value')
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
class Template < SimpleDelegator
|
44
|
+
attr_accessor :href, :method
|
45
|
+
|
46
|
+
def initialize(template, href, method)
|
47
|
+
@href = href
|
48
|
+
@method = method
|
49
|
+
super template
|
50
|
+
end
|
51
|
+
|
52
|
+
def convert_to_json
|
53
|
+
fetch('data').each_with_object({}) do |datum, json|
|
54
|
+
json[datum['name']] = datum['value']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def fill_field(name, value)
|
59
|
+
new_data = fetch('data').map {|datum|
|
60
|
+
datum = datum.clone
|
61
|
+
datum['value'] = value if datum['name'] == name
|
62
|
+
datum
|
63
|
+
}
|
64
|
+
new_template = {'data' => new_data }
|
65
|
+
Template.new(new_template, href, method)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/leif/section.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Section
|
2
|
+
attr_reader :io
|
3
|
+
def empty?() @empty end
|
4
|
+
|
5
|
+
def initialize(io)
|
6
|
+
@io = io
|
7
|
+
@empty = true
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.banner(banner, io = $stdout, &message)
|
11
|
+
new(io).banner(banner, &message)
|
12
|
+
end
|
13
|
+
|
14
|
+
def banner(banner, &message)
|
15
|
+
io.puts "-- #{banner} --"
|
16
|
+
yield self
|
17
|
+
print '[empty]' if empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def print(message)
|
21
|
+
@empty = false
|
22
|
+
Array(message).each do |line|
|
23
|
+
io.puts " #{line}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/leif/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leif
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Larry Marburger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.6.19
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: ronn
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -77,6 +91,9 @@ files:
|
|
77
91
|
- README.md
|
78
92
|
- leif.gemspec
|
79
93
|
- bin/leif
|
94
|
+
- lib/leif/cli.rb
|
95
|
+
- lib/leif/collection_json.rb
|
96
|
+
- lib/leif/section.rb
|
80
97
|
- lib/leif/version.rb
|
81
98
|
- man/leif.1
|
82
99
|
- man/leif.1.html
|