slice-ruby 0.0.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 +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
|
+

|
|
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
|