Skip to content

Conversation

@ranuseh
Copy link

@ranuseh ranuseh commented Mar 23, 2019

slack.rb

Congratulations! You're submitting your assignment!

You and your partner should collaborate on the answers to these questions.

Comprehension Questions

Question Answer
How did you go about exploring the Slack API? Did you learn anything that would be useful for your next project involving an API? We looked over the documentation and tried a different post and get request with various inputs like 40,000 chars to see the result and the type and/ or errors we were receiving. We got a lot of practice using VCR, postman, and pry. Pry was used to manipulate the data that we got back through HTTParty. The different types of tokens available and what could be done with them in the future.
Give a short summary of the request/response cycle. Where does your program fit into that scheme? The cycle beings with the client sending a request, the server processes the request and the server sends a response and the client displays the response. Our program fits into the client part of the response cycle.
How does your program check for and handle errors when using the Slack API? The send message method inside recipient there is an unless statement that checks for the correct response code and that it is okay. If those conditions are not met then we raise a SlackApiError that we defined in its own class.
Did you need to make any changes to the design work we did in class? If so, what were they? We created a method called user get and channel gets in their respective classes which used different parameters depending on whether we were getting information about users or channels. We did it that way because the parameters changed depending on whether we were working with users or channels. in hindsight, the .get method in recipient would have worked just as well.
Did you use any of the inheritance idioms we've talked about in class? How? We used an abstract class recipient and used template methods inside of recipient that was not intended to be evoked directly but rather through its children. User objects and channel objects both have a details method that treats them in the same way.
How does VCR aid in testing a program that uses an API? It prevents you from sending multiple requests or post to the server which has costs associated with it. It also prevents the over-reliance on the external API in the case that it goes down and you can do offline testing.

ranuseh and others added 30 commits March 19, 2019 13:52
…ient. Revise Recipient class tests. All tests passing
… up commented code in channel.rb and user.rb
JansenMartin and others added 28 commits March 21, 2019 18:14
…or 'select_channel' and 'select_user' for clarity
…t the user know if no channel/user has the supplied name or ID
@droberts-sea
Copy link

slack.rb

What We're Looking For

Feature Feedback
Core Requirements
Git hygiene (no slack tokens) mostly - you've included coverage files!
Comprehension questions yes
Functionality
List users/channels yes
Select user/channel yes
Show details yes
Send message yes
Program runs without crashing yes
Implementation
API errors are handled appropriately some - see inline
Inheritance model matches in-class activity yes
Inheritance idioms (abstract class, template methods, polymorphism) used appropriately yes
Methods are used to break work down into simpler tasks yes
Class and instance methods are used appropriately yes
Overall Good job overall! It is clear to me that the learning goals around understanding the request/response cycle, consuming an API, and implementing a design from scratch using inheritance have been met. There is some room for improvement around code organization and test coverage, but in general I'm happy with what I see. Keep up the hard work!

def self.channels_get
query_params = { token: ENV["SLACK_API_TOKEN"] }
return Slack::Channel.get(CHANNEL_URL, query_params)
end

Choose a reason for hiding this comment

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

Since you're already inside of Slack::Channel, you can just say return get(...) on line 33.


def self.get(url, params)
return HTTParty.get(url, query: params)
end

Choose a reason for hiding this comment

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

I think the params argument for this method is always the same: a hash containing the slack token. Could you supply that here and remove the extra argument?

Also, you should be doing things like error handling here.

In general, every time you add another layer to a piece of functionality, you should take care of some part of the puzzle in that layer. In this case, Channel.list is in charge of turning a response into an array of Channel objects, Channel.channels_get knows the URL and the query parameters, but this method doesn't add anything new.

Dotenv.load

CHANNEL_URL = "https://slack.com/api/channels.list"
USER_URL = "https://slack.com/api/users.list"

Choose a reason for hiding this comment

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

You have these constants defined a few places. In general, each constant should be defined once. This makes your code easier to change, and avoids the problem of what to do if they don't have the same value.


def clear_selected(workspace)
workspace.selected = nil
end

Choose a reason for hiding this comment

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

I would say this is a demeter violation. Instead of saying to the Workspace "your selected is now nil", it would be cleaner to call a method to ask it to clear itself.

It might be that you could move this method completely into Workspace.


unless response.code == 200 && response["ok"]
raise SlackApiError, "#{response["error"]}"
end

Choose a reason for hiding this comment

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

Good error checking here.

def show_details
details = @selected.details

rows = []

Choose a reason for hiding this comment

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

Good use of polymorphism to keep this code generic, not specific to users or channels.

@@ -0,0 +1,5 @@
{
"result": {
"covered_percent": 94.12

Choose a reason for hiding this comment

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

Make sure that your coverage files aren't included in git!

it "returns nil if given invalid identifier" do
@workspace.select_channel("INVALID_IDENTIFIER")
expect(@workspace.selected).must_equal nil
end

Choose a reason for hiding this comment

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

Nice failure case. What happens to a previously selected channel in this case?

it "returns a table for a selected channel" do
@workspace.select_channel("general")
expect(@workspace.show_details).must_be_kind_of Terminal::Table
end

Choose a reason for hiding this comment

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

What happens if you call show_details without first selecting a user or channel?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants