slice-ruby 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/Makefile +18 -0
- data/README.md +102 -0
- data/Rakefile +5 -0
- data/bin/slice +7 -0
- data/images/cli.png +0 -0
- data/lib/slice.rb +22 -0
- data/lib/slice/arguments.rb +133 -0
- data/lib/slice/client.rb +153 -0
- data/lib/slice/command_builder.rb +35 -0
- data/lib/slice/commands/base.rb +13 -0
- data/lib/slice/commands/error.rb +9 -0
- data/lib/slice/commands/request.rb +29 -0
- data/lib/slice/oauth.rb +21 -0
- data/lib/slice/resource_based_methods.rb +229 -0
- data/lib/slice/response.rb +92 -0
- data/lib/slice/response_renderer.rb +79 -0
- data/lib/slice/version.rb +3 -0
- data/slice-ruby.gemspec +32 -0
- data/spec/slice/client_spec.rb +349 -0
- data/spec/spec_helper.rb +8 -0
- metadata +266 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4ba0c0ad115c43862e724220ecb9de82bbf4e945
|
4
|
+
data.tar.gz: 33167ae57e9c4bd5172534dd9ff8135c77ca640b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e5a6fbb27f75bf8f48a10b40097ff2402f1d5a824e33ff9d60c0a9145b53712b65459bce735f22373a3cb89ce68f013038be0435da9e3db5c28bea3768f06bb4
|
7
|
+
data.tar.gz: 840b0bd98254b2cc86a55eadb81029397e4f421f0a6e69acacfd17fd2c3ad90bbc9b0ced813104f7bdf6b48cfc75b5812c91646c98897d19398490c8171072a6
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Naoki Orii
|
2
|
+
|
3
|
+
MIT License
|
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/Makefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
all: test doc
|
2
|
+
|
3
|
+
doc:
|
4
|
+
git grep -h "^\s\+# \?" lib/slice/response.rb | sed -E 's; +# ?;;' > doc/response.md
|
5
|
+
git grep -h "^\s\+# \?" lib/slice/client.rb | sed -E 's; +# ?;;' > doc/client.md
|
6
|
+
git grep -h "^\s\+# \?" lib/slice/resource_based_methods.rb | sed -E 's; +# ?;;' >> doc/client.md
|
7
|
+
|
8
|
+
release:
|
9
|
+
bundle exec rake release
|
10
|
+
|
11
|
+
setup:
|
12
|
+
gem install bundler
|
13
|
+
bundle install
|
14
|
+
|
15
|
+
test:
|
16
|
+
bundle exec rspec
|
17
|
+
|
18
|
+
.PHONY: doc release setup test
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# slice-ruby
|
2
|
+
|
3
|
+
A Ruby interface to the Slice API
|
4
|
+
|
5
|
+
## Quick start
|
6
|
+
|
7
|
+
Install via Rubygems
|
8
|
+
|
9
|
+
`gem install slice-ruby`
|
10
|
+
|
11
|
+
... or add to your Gemfile
|
12
|
+
|
13
|
+
`gem "slice-ruby", "~> 0.1"`
|
14
|
+
|
15
|
+
## Sample Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'slice'
|
19
|
+
|
20
|
+
oauth = Slice::OAuth.new(client_id, client_secret, redirect_url)
|
21
|
+
auth_url = oauth.generate_auth_url
|
22
|
+
|
23
|
+
access_token = oauth.authenticate! auth_code
|
24
|
+
|
25
|
+
client = Slice::Client.new(access_token: access_token.token)
|
26
|
+
client.list_items
|
27
|
+
client.list_orders
|
28
|
+
client.create_order(orderTitle: 'Your Amazon.com order', ...)
|
29
|
+
client.get_order(123)
|
30
|
+
client.update_order(123, orderTotal: 395, ...)
|
31
|
+
client.list_items(limit: 3, offset: 10)
|
32
|
+
client.list_items(limit: 3, offset: 10).status
|
33
|
+
client.list_items(limit: 3, offset: 10).headers
|
34
|
+
client.list_items(limit: 3, offset: 10).body
|
35
|
+
```
|
36
|
+
|
37
|
+
See [doc/client.md](doc/client.md) for more details
|
38
|
+
|
39
|
+
Also, note that `access_token` is a `OAuth2::AccessToken` object from [intridea/oauth2](https://github.com/intridea/oauth2), so you can call methods on it such as `access_token.expired?` and `access_token.refresh!`
|
40
|
+
|
41
|
+
## CLI Usage
|
42
|
+
|
43
|
+
You can use the `slice` executable to call `Slice::Client`'s methods.
|
44
|
+
|
45
|
+
```
|
46
|
+
$ slice <method> <arguments> [headers|params] [options]
|
47
|
+
| | | | |
|
48
|
+
| | | | `-- -H, --host
|
49
|
+
| | | | -a, --access-token
|
50
|
+
| | | | -c, --color
|
51
|
+
| | | | -h, --help
|
52
|
+
| | | | --header
|
53
|
+
| | | | --no-body
|
54
|
+
| | | |
|
55
|
+
| | | `------------ key=value or key:=value
|
56
|
+
| | |
|
57
|
+
| | `------------------- Key:value
|
58
|
+
| |
|
59
|
+
| `------------------------------ required arguments for the method
|
60
|
+
|
|
61
|
+
`----------------------------------------- method name
|
62
|
+
|
63
|
+
|
64
|
+
$ slice list_orders
|
65
|
+
$ slice list_merchants
|
66
|
+
$ slice list_orders limit=3 offset=2
|
67
|
+
|
68
|
+
```
|
69
|
+
|
70
|
+
### Method and Arguments
|
71
|
+
|
72
|
+
Pass [Slice::Client's method name](doc/client.md) and required arguments.
|
73
|
+
|
74
|
+
### Access token
|
75
|
+
|
76
|
+
Accepts access token via `-a, --access-token` or `SLICE_ACCESS_TOKEN` environment variable.
|
77
|
+
|
78
|
+
### Headers
|
79
|
+
|
80
|
+
To set custom request headers, use `Key:value` syntax.
|
81
|
+
|
82
|
+
```
|
83
|
+
$ slice list_items "Authorization:Bearer 1234567890abcdef1234567890abcdef"
|
84
|
+
```
|
85
|
+
|
86
|
+
### Params
|
87
|
+
|
88
|
+
Params are used for query string in the GET method, or for request body in other methods.
|
89
|
+
You can set params by `key=value` or `key:=value` syntax.
|
90
|
+
`key=value` is parsed into its String value, while `key:=value` is parsed into its JSON value (e.g. key:=17 will be `{"key":17}`).
|
91
|
+
The `slice` executable also accepts params via STDIN.
|
92
|
+
|
93
|
+
```
|
94
|
+
$ slice list_items page=2 per_page=10
|
95
|
+
$ slice create_item < params.json
|
96
|
+
```
|
97
|
+
|
98
|
+
![](images/cli.png)
|
99
|
+
|
100
|
+
## Acknowledgements
|
101
|
+
|
102
|
+
A good chunk of the code has been shamelessly taken from [increments/qiita-rb](https://github.com/increments/qiita-rb).
|
data/Rakefile
ADDED
data/bin/slice
ADDED
data/images/cli.png
ADDED
Binary file
|
data/lib/slice.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "active_support/core_ext/object/blank"
|
2
|
+
require "active_support/core_ext/string/inflections"
|
3
|
+
require "active_support/core_ext/string/strip"
|
4
|
+
require "faraday"
|
5
|
+
require "faraday_middleware"
|
6
|
+
require "json"
|
7
|
+
require "rack/utils"
|
8
|
+
require "rainbow"
|
9
|
+
require "rouge"
|
10
|
+
require "slop"
|
11
|
+
|
12
|
+
require "slice/arguments"
|
13
|
+
require "slice/client"
|
14
|
+
require "slice/command_builder"
|
15
|
+
require "slice/commands/base"
|
16
|
+
require "slice/commands/error"
|
17
|
+
require "slice/commands/request"
|
18
|
+
require "slice/oauth"
|
19
|
+
require "slice/resource_based_methods"
|
20
|
+
require "slice/response"
|
21
|
+
require "slice/response_renderer"
|
22
|
+
require "slice/version"
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Slice
|
2
|
+
class Arguments
|
3
|
+
def initialize(argv)
|
4
|
+
@argv = argv
|
5
|
+
end
|
6
|
+
|
7
|
+
def access_token
|
8
|
+
slop_options["access-token"] || ENV["SLICE_ACCESS_TOKEN"]
|
9
|
+
end
|
10
|
+
|
11
|
+
def arguments
|
12
|
+
parsed_argv_data[:arguments]
|
13
|
+
end
|
14
|
+
|
15
|
+
def color
|
16
|
+
slop_options["color"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def error_message
|
20
|
+
slop_options.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def headers
|
24
|
+
parsed_argv_data[:headers]
|
25
|
+
end
|
26
|
+
|
27
|
+
def host
|
28
|
+
slop_options["host"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_name
|
32
|
+
ARGV[0]
|
33
|
+
end
|
34
|
+
|
35
|
+
def params
|
36
|
+
params_from_stdin.merge(parsed_argv_data[:params])
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_body
|
40
|
+
!slop_options["no-body"]
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_header
|
44
|
+
slop_options["header"]
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid?
|
48
|
+
has_valid_slop_options? && has_valid_method_name? && has_valid_arguments? && !has_invalid_json_input?
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def has_input_from_stdin?
|
54
|
+
has_pipe_input? || has_redirect_input?
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_invalid_json_input?
|
58
|
+
params_from_stdin
|
59
|
+
false
|
60
|
+
rescue JSON::ParserError
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def has_pipe_input?
|
65
|
+
File.pipe?(STDIN)
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_redirect_input?
|
69
|
+
File.select([STDIN], [], [], 0) != nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_valid_arguments?
|
73
|
+
-(Client.instance_method(method_name).arity) - 1 == arguments.length
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_valid_method_name?
|
77
|
+
!method_name.nil? && Client.instance_methods.include?(method_name.to_sym)
|
78
|
+
end
|
79
|
+
|
80
|
+
def has_valid_slop_options?
|
81
|
+
!slop_options["help"]
|
82
|
+
rescue
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
def params_from_stdin
|
87
|
+
@params_from_stdin ||= begin
|
88
|
+
if has_input_from_stdin?
|
89
|
+
JSON.parse(STDIN.read)
|
90
|
+
else
|
91
|
+
{}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def parsed_argv_data
|
97
|
+
@parsed_argv_data ||= begin
|
98
|
+
params = {}
|
99
|
+
headers = {}
|
100
|
+
arguments = []
|
101
|
+
ARGV[1..-1].each do |section|
|
102
|
+
case
|
103
|
+
when /(?<key>.+):(?<value>[^=]+)/ =~ section
|
104
|
+
headers[key] = value
|
105
|
+
when /(?<key>.+):=(?<value>.+)/ =~ section
|
106
|
+
params[key] = JSON.parse(%<{"key":#{value}}>)["key"]
|
107
|
+
when /(?<key>.+)=(?<value>.+)/ =~ section
|
108
|
+
params[key] = value
|
109
|
+
else
|
110
|
+
arguments << section
|
111
|
+
end
|
112
|
+
end
|
113
|
+
{
|
114
|
+
arguments: arguments,
|
115
|
+
headers: headers,
|
116
|
+
params: params,
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def slop_options
|
122
|
+
@slop_options ||= Slop.parse!(@argv) do
|
123
|
+
banner "Usage: slice <method> [arguments] [headers|params] [options]"
|
124
|
+
on "H", "host=", "Change API server's host"
|
125
|
+
on "a", "access-token=", "Access token"
|
126
|
+
on "c", "color", "Color output"
|
127
|
+
on "h", "help", "Display help message"
|
128
|
+
on "header", "Show response header"
|
129
|
+
on "no-body", "Hide response body"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/slice/client.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "slice/resource_based_methods"
|
3
|
+
require "slice/version"
|
4
|
+
|
5
|
+
## Slice::Client
|
6
|
+
# A class for API client to send HTTP requests.
|
7
|
+
#
|
8
|
+
module Slice
|
9
|
+
class Client
|
10
|
+
DEFAULT_ACCEPT = "application/json"
|
11
|
+
|
12
|
+
DEFAULT_HOST = "api.slice.com"
|
13
|
+
|
14
|
+
DEFAULT_USER_AGENT = "Slice Ruby Gem #{Slice::VERSION}"
|
15
|
+
|
16
|
+
DEFAULT_HEADERS = {
|
17
|
+
"Accept" => DEFAULT_ACCEPT,
|
18
|
+
"User-Agent" => DEFAULT_USER_AGENT,
|
19
|
+
}
|
20
|
+
|
21
|
+
include ResourceBasedMethods
|
22
|
+
|
23
|
+
# ### Slice::Client.new(options = {})
|
24
|
+
# Creates a new instance of `Slice::Client` class.
|
25
|
+
# `options` can have following key-values:
|
26
|
+
#
|
27
|
+
# * `access_token` - (String) Access token issued to authenticate and authorize user.
|
28
|
+
# * `host` - (String) Hostname where this client accesses to.
|
29
|
+
#
|
30
|
+
# ```rb
|
31
|
+
# Slice::Client.new
|
32
|
+
# Slice::Client.new(access_token: "...")
|
33
|
+
# ```
|
34
|
+
#
|
35
|
+
def initialize(access_token: nil, host: nil, ssl: true)
|
36
|
+
@access_token = access_token
|
37
|
+
@host = host
|
38
|
+
@ssl = ssl
|
39
|
+
end
|
40
|
+
|
41
|
+
# ### Slice::Client#get(path, params = nil, headers = nil)
|
42
|
+
# Sends GET request with given parameters, then returns a `Slice::Response`.
|
43
|
+
# `params` are url-encoded and used as URI query string.
|
44
|
+
#
|
45
|
+
# ```rb
|
46
|
+
# client.get("/api/v1/items", page: 2)
|
47
|
+
# ```
|
48
|
+
#
|
49
|
+
def get(path, params = nil, headers = nil)
|
50
|
+
process(:get, path, params, headers)
|
51
|
+
end
|
52
|
+
|
53
|
+
# ### Slice::Client#post(path, params = nil, headers = nil)
|
54
|
+
# Sends POST request with given parameters, then returns a Slice::Response.
|
55
|
+
# `params` are JSON-encoded and used as request body.
|
56
|
+
#
|
57
|
+
# ```rb
|
58
|
+
# client.post("/api/v1/items", category: "...", price: "...")
|
59
|
+
# ```
|
60
|
+
#
|
61
|
+
def post(path, params = nil, headers = nil)
|
62
|
+
process(:post, path, params, headers)
|
63
|
+
end
|
64
|
+
|
65
|
+
# ### Slice::Client#patch(path, params = nil, headers = nil)
|
66
|
+
# Sends PATCH request with given parameters, then returns a Slice::Response.
|
67
|
+
# `params` are JSON-encoded and used as request body.
|
68
|
+
#
|
69
|
+
# ```rb
|
70
|
+
# client.patch("/api/v1/items/123", title: "...", body: "...")
|
71
|
+
# ```
|
72
|
+
#
|
73
|
+
def patch(path, params = nil, headers = nil)
|
74
|
+
process(:patch, path, params, headers)
|
75
|
+
end
|
76
|
+
|
77
|
+
# ### Slice::Client#put(path, params = nil, headers = nil)
|
78
|
+
# Sends PUT request, then returns a Slice::Response.
|
79
|
+
# `params` are JSON-encoded and used as request body.
|
80
|
+
#
|
81
|
+
# ```rb
|
82
|
+
# client.put("/api/v1/items/123")
|
83
|
+
# ```
|
84
|
+
#
|
85
|
+
def put(path, params = nil, headers = nil)
|
86
|
+
process(:put, path, params, headers)
|
87
|
+
end
|
88
|
+
|
89
|
+
# ### Slice::Client#delete(path, params = nil, headers = nil)
|
90
|
+
# Sends DELETE request, then returns a Slice::Response.
|
91
|
+
# `params` are url-encoded and used as URI query string.
|
92
|
+
#
|
93
|
+
# ```rb
|
94
|
+
# client.delete("/api/v1/items/123")
|
95
|
+
# ```
|
96
|
+
#
|
97
|
+
def delete(path, params = nil, headers = nil)
|
98
|
+
process(:delete, path, params, headers)
|
99
|
+
end
|
100
|
+
|
101
|
+
# ### Slice::Client#connection
|
102
|
+
# Returns a Faraday::Connection to customize by your favorite middlewares.
|
103
|
+
#
|
104
|
+
# ```rb
|
105
|
+
# client.connection.response :logger
|
106
|
+
# ```
|
107
|
+
#
|
108
|
+
def connection
|
109
|
+
@connection ||= Faraday.new(faraday_client_options) do |connection|
|
110
|
+
connection.request :json
|
111
|
+
connection.response :json
|
112
|
+
connection.adapter Faraday.default_adapter
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def default_headers
|
119
|
+
headers = DEFAULT_HEADERS.clone
|
120
|
+
headers["Authorization"] = "Bearer #{@access_token}" if @access_token
|
121
|
+
headers
|
122
|
+
end
|
123
|
+
|
124
|
+
def faraday_client_options
|
125
|
+
{
|
126
|
+
headers: default_headers,
|
127
|
+
ssl: {
|
128
|
+
verify: @ssl,
|
129
|
+
},
|
130
|
+
url: url_prefix,
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
def host
|
135
|
+
@host || DEFAULT_HOST
|
136
|
+
end
|
137
|
+
|
138
|
+
def process(request_method, path, params, headers)
|
139
|
+
Slice::Response.new(
|
140
|
+
connection.send(
|
141
|
+
request_method,
|
142
|
+
URI.escape(path),
|
143
|
+
params,
|
144
|
+
headers,
|
145
|
+
)
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def url_prefix
|
150
|
+
"https://#{host}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|