Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add response_metadata to Web API errors #311

Merged
merged 12 commits into from
Mar 10, 2020
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 0.14.6 (Next)

* [#305](https://github.com/slack-ruby/slack-ruby-client/pull/305): Added `admin.inviteRequests.approve`, `admin.inviteRequests.deny`, `admin.inviteRequests.list`, `admin.inviteRequests.approved.list`, `admin.inviteRequests.denied.list`, `admin.teams.create`, `admin.teams.list`, `admin.teams.admins.list`, `admin.teams.owners.list`, `admin.teams.settings`, `admin.teams.settings.setIcon`, `admin.teams.settings.setName`, `admin.teams.settings.setDescription`, `admin.users.assign`, `admin.users.invite`, `admin.users.remove`, `admin.users.setAdmin`, `admin.users.setOwner` and `admin.users.setRegular` endpoints - [@manuelmeurer](https://github.com/manuelmeurer).
* [#311](https://github.com/slack-ruby/slack-ruby-client/pull/311): Made Web API `response_metadata` more accessible in errors - [@jmanian](https://github.com/jmanian).
* Your contribution here.

### 0.14.5 (2019/12/23)
Expand Down
39 changes: 22 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ A Ruby client for the Slack [Web](https://api.slack.com/web), [RealTime Messagin
- [Using the Legacy API Token](#using-the-legacy-api-token)
- [Global Settings](#global-settings)
- [Web Client](#web-client)
- [Test Auth](#test-auth)
- [Send Messages](#send-messages)
- [List Channels](#list-channels)
- [Upload a File](#upload-a-file)
- [Get Channel Info](#get-channel-info)
- [Get User Info](#get-user-info)
- [Search for a User](#search-for-a-user)
- [Other](#other)
- [Web Client Examples](#web-client-examples)
- [Test Auth](#test-auth)
- [Send Messages](#send-messages)
- [List Channels](#list-channels)
- [Upload a File](#upload-a-file)
- [Get Channel Info](#get-channel-info)
- [Get User Info](#get-user-info)
- [Search for a User](#search-for-a-user)
- [Other](#other)
- [Web Client Options](#web-client-options)
- [Pagination Support](#pagination-support)
- [Error Handling](#error-handling)
Expand Down Expand Up @@ -122,14 +123,18 @@ logger | An optional logger, defaults to `::Logger.new(STDOUT)` at `Logger

The Slack Web API allows you to build applications that interact with Slack.

#### Test Auth
#### Web Client Examples

Here are some examples of how to use the web client with the Web API.

##### Test Auth

```ruby
client = Slack::Web::Client.new
client.auth_test
```

#### Send Messages
##### Send Messages

Send messages with [chat_PostMessage](https://api.slack.com/methods/chat.postMessage).

Expand All @@ -141,7 +146,7 @@ See a fully working example in [examples/hi_web](examples/hi_web/hi.rb).

![](examples/hi_web/hi.gif)

#### List Channels
##### List Channels

List channels with [channels_list](https://api.slack.com/methods/channels.list).

Expand All @@ -151,7 +156,7 @@ channels = client.channels_list.channels
general_channel = channels.detect { |c| c.name == 'general' }
```

#### Upload a File
##### Upload a File

Upload a file with [files_upload](https://api.slack.com/methods/files.upload).

Expand All @@ -166,7 +171,7 @@ client.files_upload(
)
```

### Get Channel Info
##### Get Channel Info

You can use a channel ID or name (prefixed with `#`) in all functions that take a `:channel` argument. Lookup by name is not supported by the Slack API and the `channels_id` method called invokes `channels_list` in order to locate the channel ID.

Expand All @@ -178,7 +183,7 @@ client.channels_info(channel: 'C04KB5X4D') # calls channels_info
client.channels_info(channel: '#general') # calls channels_list followed by channels_info
```

### Get User Info
##### Get User Info

You can use a user ID or name (prefixed with `@`) in all functions that take a `:user` argument. Lookup by name is not supported by the Slack API and the `users_id` method called invokes `users_list` in order to locate the user ID.

Expand All @@ -190,15 +195,15 @@ client.users_info(user: 'U092BDCLV') # calls users_info
client.users_info(user: '@dblock') # calls users_list followed by users_info
```

### Search for a User
##### Search for a User

Constructs an in-memory index of users and searches it. If you want to use this functionality, add the [picky](https://github.com/floere/picky) gem to your project's Gemfile.

```ruby
client.users_search(user: 'dblock')
```

#### Other
##### Other

Refer to the [Slack Web API Method Reference](https://api.slack.com/methods) for the list of all available functions.

Expand Down Expand Up @@ -270,7 +275,7 @@ all_members # many thousands of team members retrieved 10 at a time

#### Error Handling

If a request fails, a `Slack::Web::Api::Errors::SlackError` will be raised. The error message contains the error code. In case of multiple errors, the error codes are separated by commas. The original response is also accessible using the `response` attribute.
If a request fails, a `Slack::Web::Api::Errors::SlackError` will be raised. The error message contains the error code, which is also accessible with `slack_error.error`. In case of multiple errors, the error message contains the error codes separated by commas, or they are accessible as an array with `slack_error.errors`. The original response is also accessible using the `response` attribute. The `response_metadata` is accessible with `slack_error.response_metadata`.

If you exceed [Slack’s rate limits](https://api.slack.com/docs/rate-limits), a `Slack::Web::Api::Errors::TooManyRequestsError` will be raised instead.

Expand Down
12 changes: 12 additions & 0 deletions lib/slack/web/api/errors/slack_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ def initialize(message, response = nil)
super message
@response = response
end

def error
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort of a horrible name. I used it because it's the name of the field in the response body, but I'm open to changing it. One alternative is error_code (and error_codes below).

response.body.error
end

def errors
response.body.errors
end

def response_metadata
response.body.response_metadata
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/slack/web/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Client

def initialize(options = {})
Slack::Web::Config::ATTRIBUTES.each do |key|
send("#{key}=", options[key] || Slack::Web.config.send(key))
send("#{key}=", options.fetch(key, Slack::Web.config.send(key)))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This turned out to not be directly relevant, but I noticed that if there was a truthy value in the config that it could not be overridden with a falsey value.

end
@logger ||= Slack::Config.logger || Slack::Logger.default
@token ||= Slack.config.token
Expand Down
76 changes: 76 additions & 0 deletions spec/fixtures/slack/web/views_open_error.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions spec/slack/web/api/errors/slack_error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@
rescue described_class => e
expect(e.response).not_to be_nil
expect(e.response.status).to eq 200
expect(e.message).to eql 'not_authed'
expect(e.error).to eql 'not_authed'
expect(e.response_metadata).to be_nil
end
end

it 'provides access to any response_metadata', vcr: { cassette_name: 'web/views_open_error' } do
begin
client.views_open(trigger_id: 'trigger_id', view: {})
raise 'Expected to receive Slack::Web::Api::Errors::SlackError.'
rescue described_class => e
expect(e.response).not_to be_nil
expect(e.response.status).to eq 200
expect(e.message).to eql 'invalid_arguments'
expect(e.error).to eql 'invalid_arguments'
expect(e.response_metadata).to eq(
'messages' => [
"[ERROR] missing required field: title [json-pointer:\/view]",
"[ERROR] missing required field: blocks [json-pointer:\/view]",
"[ERROR] missing required field: type [json-pointer:\/view]"
]
)
end
end
end
9 changes: 8 additions & 1 deletion spec/slack/web/faraday/response/raise_error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@
end

context 'with a single error in the body' do
let(:body) { { 'error' => 'already_in_channel' } }
let(:body) do
{
'ok' => false,
'error' => 'already_in_channel',
'response_metadata' => { 'messages' => [] }
}
end

it 'raises a SlackError with the error message' do
expect { raise_error_obj.on_complete(env) }.to(
Expand All @@ -41,6 +47,7 @@
context 'with multiple errors in the body' do
let(:body) do
{
'ok' => false,
'errors' => [
{ 'error' => 'already_in_channel' },
{ 'error' => 'something_else_terrible' }
Expand Down