slice-ruby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in slice.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -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).
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new("spec")
5
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+ require "slice"
4
+
5
+ builder = Slice::CommandBuilder.new(ARGV)
6
+ command = builder.call
7
+ command.call
Binary file
@@ -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
@@ -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