If you want to follow along, set up a new workspace using the base-ruby template repository.
The API tokens for this project can be found in the corresponding Canvas assignment.
So far, we've been using our browser's address bar, <a>
tags, and <form>
tags to visit URLs.
More formally, what we've been doing is: placing HTTP requests. There are also many other ways to place HTTP requests — we've already seen one, in Ruby's URI.open()
method.
An HTTP request is actually comprised of more things than just the URL where the resource is located at. When we place a request, we specify:
-
A request line. E.g.:
GET /fortunes/aries HTTP/1.1
The first part is known as the HTTP method, a.k.a. HTTP verb. Then comes the URL, and finally comes the version of the HTTP protocol being used.
The browser's address bar can only use the
GET
HTTP verb, which makes sense because the best practice is to useGET
to say that you're trying to read the resource located at the specified URL. When we're doing our normal browsing, we're usually reading things (and not creating, updating, or deleting).For the rest of the CRUD operations, best practice is to use:
POST
→ creatingPATCH
→ updatingDELETE
→ deleting
<a>
elements can also only placeGET
requests, like the browser's address bar. However,<form>
elements have the ability to placePOST
requests if you add themethod="post"
attribute to the opening<form>
tag. In fact, most<form>
s usePOST
, since the job of most forms is to create information.PATCH
andDELETE
are, oddly, not possible in plain HTML. Later on, we'll use JavaScript to achieve that. For now, we'll usePOST
for updating and stick withGET
for deleting. -
A set of header fields allow us to specify things like our user agent (e.g. what browser we're using), authentication information, and more.
-
A body (optional). This is where we can supply information along with our request, like image uploads or other form input data.
Read more about HTTP requests here.
- Visit https://hoppscotch.io/
- Try making a
GET
request to a JSON API: - Try making
GET
requests to JSON APIs that require authentication via query string parameters: - Try placing a
GET
to the URL of a regular HTML page, like "https://wikipedia.org". (You will need to check "Proxy" in the dialog that appears the first time.) You will get back the HTML source code of the page. Hoppscotch is really just a special browser built for exploring APIs. - There are many advantages of using a tool like Hoppscotch, which is built specifically for exploring APIs, over using your browser's address bar to place these requests:
- It indents and formats the JSON responses.
- You can use
POST
,PATCH
,DELETE
, and any other HTTP verbs; not justGET
. - You can include headers in your request, which many APIs require for authentication (as opposed to just sticking your token in a query string parameter).
- You can sign up for an account and save the requests you are making, for future reference.
- For example, try placing a request to the following:
- Verb:
POST
- URL:
https://api.twilio.com/2010-04-01/Accounts/REPLACE_WITH_YOUR_TWILIO_ACCOUNT_SID/Messages
- Body tab:
- Switch
Content Type
toapplication/x-www-form-urlencoded
. - Add three key-value pairs:
From
=>+19876543210
(replace with our Twilio sending number)To
=>+13129876543
(replace with your own phone number, to receive the SMS)Body
=>Hello from Hoppscotch!
- Switch
- Authorization tab:
- Switch
Authorization Type
toBasic Auth
. Username
=> paste our Twilio account SIDPassword
=> paste our Twilio API token
- Switch
- Then click "Send". You should receive a text!
- Verb:
I learned how to fill out those fields by exploring the API documentation, looking at the examples, and lots of trial and error. But once I got a message to successfully send from Hoppscotch, I knew I would be good to go in Ruby!
Once I've explored an API by reading the docs and using Hoppscotch to make sure I can successfully place the requests, I then turn to translating the requests into Ruby.
Ruby's built in URI.open()
method is a super-convenient way to get started placing HTTP requests, but it's sort of like your browser's address bar; it can only place GET
requests.
Instead, let's use the wonderful http.rb gem, which makes it easy to place any kind of request.
First, let's install the gem. At a Terminal prompt:
gem install http
In a Ruby script:
require "http"
p HTTP.get("https://api.exchangerate.host/convert?from=USD&to=EUR")
This returns the body of that page as a String
. Then, we can use the JSON.parse()
method to convert that String
into a much more useful Hash
:
require "http"
raw_response = HTTP.get("https://api.exchangerate.host/convert?from=USD&to=EUR")
parsed_response = JSON.parse(raw_response)
info_hash = parsed_response.fetch("info")
result = info_hash.fetch("rate")
p result
The nice thing is that we can place more involved requests with HTTP
. Let's place the same request that we did above using Hoppscotch to send an SMS with Twilio:
require "http"
response = HTTP.
basic_auth(
{
:user => ENV.fetch("TWILIO_ACCOUNT_SID"),
:pass => ENV.fetch("TWILIO_AUTH_TOKEN")
}
).
post(
"https://api.twilio.com/2010-04-01/Accounts/AC28922e0822d827ee29834fe1dc6f681e/Messages",
:form => {
"From" => ENV.fetch("TWILIO_SENDING_NUMBER"),
"To" => "+13129876543", # Put your own phone number here if you want to see it in action
"Body" => "Hello from http.rb!"
}
)
p response.to_s
Be sure that you have the needed environment variables.
As we can see, once we've done our homework by reading the API docs, experimenting with Hoppscotch, and figuring out the URLs, parameters, and authentication — then actually using the API from Ruby is pretty straightforward. Doing the homework and figuring out what we want to do is, as usual, the hard part.
But, for most popular APIs, it gets even more straightforward — someone has usually written a gem to interact with the raw URLs and parameters for us. For example, Twilio have themselves written and shared a Ruby gem called twilio-ruby. Let's try it out:
Make sure we have the gem installed:
gem install twilio-ruby
In a Ruby script:
require "twilio-ruby"
# Create an instance of the Twilio Client and authenticate with your API key
twilio_client = Twilio::REST::Client.new(ENV.fetch("TWILIO_ACCOUNT_SID"), ENV.fetch("TWILIO_AUTH_TOKEN"))
# Craft your SMS as a Hash literal with three keys
sms_info = {
:from => ENV.fetch("TWILIO_SENDING_NUMBER"),
:to => "+19876543210", # Put your own phone number here if you want to see it in action
:body => "Hello from twilio-ruby!"
}
# Send your SMS!
twilio_client.api.account.messages.create(**sms_info)
For interacting with the OpenAI API, we're going to skip directly to using an API client.
Make sure we have the gem installed:
gem install ruby-openai
In a Ruby script:
require "openai"
openai_client = OpenAI::Client.new(
access_token: ENV.fetch("OPENAI_TOKEN"),
request_timeout: 240 # Optional parameter; increases the number of seconds before a request times out
)
response = openai_client.chat(
parameters: {
model: "gpt-3.5-turbo", # Required. I recommend using gpt-3.5-turbo while developing, because it's a LOT cheaper than gpt-4
messages: [
{ role: "system", content: "You are a helpful assistant that talks like Shakespeare." },
{ role: "user", content: "Hello!"}
],
temperature: 0.7,
}
)
p response.fetch("choices").at(0)
You can keep the conversation going by adding GPT's previous response to the messages
array, as well as the next user prompt. Then re-submit the request for the next chat response!