<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jesse vonBergen</title>
    <description>The latest articles on DEV Community by Jesse vonBergen (@avocoaster).</description>
    <link>https://dev.to/avocoaster</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F736634%2F76ea187f-1886-4323-8c99-18d1be108bee.png</url>
      <title>DEV Community: Jesse vonBergen</title>
      <link>https://dev.to/avocoaster</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avocoaster"/>
    <language>en</language>
    <item>
      <title>What exactly is a Ruby binding?</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sun, 16 Mar 2025 18:58:00 +0000</pubDate>
      <link>https://dev.to/avocoaster/what-exactly-is-a-ruby-binding-340g</link>
      <guid>https://dev.to/avocoaster/what-exactly-is-a-ruby-binding-340g</guid>
      <description>&lt;p&gt;If you're a Ruby developer, you might have encountered something like the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;binding.pry&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;binding.irb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;binding.break&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your code runs one of these expressions, the execution will halt, and a REPL session will start from that context.&lt;/p&gt;

&lt;p&gt;Have you ever wondered what a "binding" is exactly?  Or how to use one? I'm hoping to answer both questions here, so let's go! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a binding?
&lt;/h2&gt;

&lt;p&gt;A Ruby binding is...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An encapsulation of the execution context at some particular place in the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;If you'd like to see exactly how Ruby creates the Binding class, you can find the source code &lt;a href="https://github.com/ruby/ruby/blob/70a9e5f6eb42cb1badba13d118f3c0d4106a3fe1/proc.c#L4508" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, a binding encapsulates or "takes a snapshot" of a particular place in the code during execution. To illustrate this, imagine holding a photograph of an old-fashioned telephone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzu0diw5784217dzhbuj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzu0diw5784217dzhbuj.jpg" alt="Photo by Eckhard Hoehmann on Unsplash" width="800" height="874"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@ecki77?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Eckhard Hoehmann&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/gray-rotary-telephone-on-brown-table-NKKvASHfrG4?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This photograph was taken before smart phones were invented. What if you could jump back into 1984? You might ask people about smart phones, to which they would give you a blank stare.&lt;br&gt;&lt;br&gt;
Similarly, if you jumped into a photo taken in 2010 and asked about ChatGPT, you'd also receive "deer in headlights".  In this sense, the photo is like the binding.&lt;/p&gt;

&lt;p&gt;With bindings, we can jump back into the way things were. &lt;/p&gt;
&lt;h2&gt;
  
  
  Using bindings
&lt;/h2&gt;

&lt;p&gt;Ruby makes this easy. Simply invoke the method &lt;code&gt;binding&lt;/code&gt;, available globally.  It will return an instance of the class &lt;code&gt;Binding&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;binding&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Binding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The class itself has no variables, constants, or methods of its own, but the instances will encapsulate the context upon instantiation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Capture context #1&lt;/span&gt;
&lt;span class="n"&gt;year_1984&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;binding&lt;/span&gt;

&lt;span class="n"&gt;i_phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:invented&lt;/span&gt;

&lt;span class="c1"&gt;# Capture context #2&lt;/span&gt;
&lt;span class="n"&gt;year_2010&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;binding&lt;/span&gt;

&lt;span class="n"&gt;chat_gpt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:invented&lt;/span&gt;

&lt;span class="c1"&gt;# Capture context #3&lt;/span&gt;
&lt;span class="n"&gt;year_2025&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;binding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In 1984, neither technologies were invented yet.  In 2010 only the iPhone was invented, and in 2025, both have been invented.&lt;/p&gt;

&lt;p&gt;We can see this clearly through the &lt;code&gt;#eval&lt;/code&gt; method which takes a String argument (something to evaluate) and an optional binding.  If not specified, it defaults to the current context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# evaluating from the first context...&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"i_phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_1984&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; NameError&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chat_gpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_1984&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; NameError&lt;/span&gt;

&lt;span class="c1"&gt;# evaluating from the second context...&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"i_phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_2010&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; :invented&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chat_gpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_2010&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; NameError&lt;/span&gt;

&lt;span class="c1"&gt;# evaluating from the third context...&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"i_phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_2025&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; :invented&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"chat_gpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_2025&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; :invented&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Beginner's Guide to Curl: Part 5 - Setting Headers</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sun, 16 Apr 2023 22:23:45 +0000</pubDate>
      <link>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-5-setting-headers-16g4</link>
      <guid>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-5-setting-headers-16g4</guid>
      <description>&lt;p&gt;HTTP requests are sent with metadata contained in headers. This includes data such as the request method, authentication credentials, and cookies.&lt;/p&gt;

&lt;p&gt;Headers consist of a "field name" and "field value" separated by a colon.  Multi-word field names are separated by dashes and are case-insensitive.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Field-Name: Some Value&lt;/code&gt; or &lt;code&gt;field-name: Some Value&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can see exactly which headers are being passed by adding the &lt;code&gt;-v&lt;/code&gt; or &lt;code&gt;--verbose&lt;/code&gt; flag to your curl requests.  There is also a free service that has an API endpoint that echos your request headers back to you as a JSON response.&lt;/p&gt;

&lt;p&gt;Type the following command to see the default headers sent by curl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://httpbin.org/headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got this JSON response in return.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpbin.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"curl/7.85.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default curl accepts any content type in return, "*/*".  Normally the "Accept" header would specify the MIME type the request is expecting in return, such as "text/html" or "application/json".&lt;/p&gt;

&lt;p&gt;The "Host" header is set because of the URL supplied to curl.&lt;/p&gt;

&lt;p&gt;The "User-Agent" in this case is the curl application, but let's switch that now.  &lt;/p&gt;

&lt;p&gt;Send this instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'User-Agent: Mozilla/5.0'&lt;/span&gt; https://httpbin.org/headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, as you can see, the response shows your agent header set to 'Mozilla/5.0'.  All headers can be set in Curl with the &lt;code&gt;-H&lt;/code&gt; or &lt;code&gt;--header&lt;/code&gt;.  Headers can be placed before or after the URL. &lt;br&gt;
 If you want to set multiple headers at once, you'll need us use multiple flags.  Here's a way you can construct a complex curl request on multiple lines using the backlash to escape newlines.&lt;/p&gt;

&lt;p&gt;(By the way, you can make up your own headers, and you don't have to prefix them with an 'X'.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://httpbin.org/headers &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Accept: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Referer: https://dev.to'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'My-Cool-Custom-Header: foo'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Authorization Header&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the main usages of HTTP headers is authentication.  Interestingly the header for this is called 'Authorization'.  I guess these two concepts are similar enough. &lt;/p&gt;

&lt;p&gt;Authorization headers work by specifying a &lt;code&gt;scheme&lt;/code&gt; followed by a space and the value.  Here's an example.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Authorization: basic username:password&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here's an API to test out basic auth.  You construct the endpoint using &lt;code&gt;basic-auth&lt;/code&gt; as the first segment followed by the username of your choice, and finally the password.  In our case, we will attempt to authenticate via the endpoint &lt;code&gt;basic-auth/username/password&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The API will either return a &lt;code&gt;200&lt;/code&gt; or &lt;code&gt;401&lt;/code&gt; response.  Supplying the &lt;code&gt;-i&lt;/code&gt; or &lt;code&gt;--include&lt;/code&gt; flags will reveal the response headers and status code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; https://httpbin.org/basic-auth/username/password &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: basic username:password`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Huh?  Why is it a 401?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/2 401
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because the internet specifies that basic HTTP auth credentials be encoded using base64.&lt;/p&gt;

&lt;p&gt;Base 64 is not encryption.  Nothing about it is secure, it's just a different encoding.  This &lt;a href="https://www.youtube.com/watch?v=aUdKd0IFl34" rel="noopener noreferrer"&gt;video&lt;/a&gt; offers a great explanation.&lt;/p&gt;

&lt;p&gt;You can easily encode anything you want in Base64 without leaving the command line.  Just echo an expression and pipe it to the &lt;code&gt;base64&lt;/code&gt; cli.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; username:password | &lt;span class="nb"&gt;base64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the result as &lt;code&gt;dXNlcm5hbWU6cGFzc3dvcmQ=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ok, now that we have the string 'username:password' encoded in Base64, let's try the API again, and see if we can successfully authenticate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; https://httpbin.org/basic-auth/username/password &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: basic dXNlcm5hbWU6cGFzc3dvcmQ='&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the response!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;HTTP/2 200
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"authenticated"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
  &lt;span class="s2"&gt;"user"&lt;/span&gt;: &lt;span class="s2"&gt;"username"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooray!&lt;/p&gt;

&lt;p&gt;But that seems pretty tedious.  Thankfully, the developers of Curl already thought of that.  That's why Curl provides a special option for the authorization header.  Just provide the &lt;code&gt;-u&lt;/code&gt; or &lt;code&gt;--user&lt;/code&gt; flag followed by the &lt;code&gt;username:password&lt;/code&gt; in plain text.  You can specify the the scheme with the &lt;code&gt;--basic&lt;/code&gt;; however, it's already basic by default.  Curl will then encode your username and password for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; https://httpbin.org/basic-auth/apple/banana
    &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s1"&gt;'apple:banana'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that Curl really did encode the credentials, just supply the &lt;code&gt;-v&lt;/code&gt; or &lt;code&gt;--verbose&lt;/code&gt; flag to see all request headers.  In my case with apple and banana, my header looked like this.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;authorization: Basic YXBwbGU6YmFuYW5h&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Another type of HTTP authorization is called &lt;code&gt;bearer&lt;/code&gt;.  Instead of supplying a username and password, you would use the word 'bearer' followed by a space and some sort of token.  Oftentimes these tokens are randomly generated keys or actual data that's gone through a hashing algorithm, such as a JSON Web Token (JWT) which contains JSON data.&lt;/p&gt;

&lt;p&gt;Once you're confident supplying header data in your Curl requests, you'll find it easy and fast to test out APIs straight from the command line.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>http</category>
      <category>zsh</category>
      <category>curl</category>
    </item>
    <item>
      <title>A Beginner's Guide to Curl: Part 4 - Json APIs</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sat, 04 Mar 2023 18:41:07 +0000</pubDate>
      <link>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-4-2ilg</link>
      <guid>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-4-2ilg</guid>
      <description>&lt;p&gt;Now let's start using curl to interact with APIs. A popular data format that get's passed around the internet is Json (Javascript Object Notation).&lt;/p&gt;

&lt;p&gt;Json is structured by key-value pairs inside curly brackets and lists of key-value pairs inside square brackets.  It uses double quotes and colons.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jesse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"articles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A Beginner's Guide to Curl: Part 4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"langauge"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"English"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A Beginner's Guide to Curl: Part 5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"length"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"words"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27321&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's grab a Json response from a free Pokemon API service found at &lt;a href="https://pokeapi.co" rel="noopener noreferrer"&gt;https://pokeapi.co&lt;/a&gt;.  Notice it's .co not .com.&lt;/p&gt;

&lt;p&gt;Webservices that offer API endpoints typically namespace them with &lt;code&gt;/api&lt;/code&gt; and the API version, in this case &lt;code&gt;/v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://pokeapi.co/api/v2/pokemon/charizard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have received a large block of Json printed to your STDOUT.  It's pretty hard to read isn't it?  &lt;/p&gt;

&lt;p&gt;There are several tools you could use to pipe the HTTP Json response into a human-readable format.  We'll use something called "JQ".  You can read about it and download it at &lt;a href="https://stedolan.github.io/jq/" rel="noopener noreferrer"&gt;https://stedolan.github.io/jq/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're on MacOS and use Homebrew as your package manager, you can type this in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now curl the same endpoint but this time pipe the response into JQ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://pokeapi.co/api/v2/pokemon/charizard | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the Json should be indented in a way you can read it easily.  It may even have color!&lt;/p&gt;

&lt;p&gt;Currently, our data is only printed to our STDOUT, it's not persisted anywhere.  We want to keep this around for future use.  Do you remember the curl option to do this?  Scroll down after you take a guess.&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;If you guessed &lt;code&gt;--output&lt;/code&gt; or &lt;code&gt;-o&lt;/code&gt;, you're correct!&lt;/p&gt;

&lt;p&gt;Let's save our Json to a file called charizard.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; charizard.json https://pokeapi.co/api/v2/pokemon/charizard 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's grab another one.  Pick another Pokemon and substitute the API endpoint with its name.  Also change the file name to match.  For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; dragonite.json https://pokeapi.co/api/v2/pokemon/dragonite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't know about you, but these Json payloads contain more information then I need.  The JQ tool has a way to scope the data by specific fields.  There is a learning curve, but if you follow along, you'll at least get a basic understanding.&lt;/p&gt;

&lt;p&gt;The Json payload has three keys that we're interested in: "name", "id", and "types".  Type this command, and you'll get the response scoped to only these attributes and printed to your console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://pokeapi.co/api/v2/pokemon/charizard | jq &lt;span class="s1"&gt;'{name, id, types}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to refine this slightly, let's only grab each type name and put it in an array.  Here's what that would look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://pokeapi.co/api/v2/pokemon/charizard | jq &lt;span class="s1"&gt;'{name, id, types: [.types[].type.name]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output should be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"charizard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"fire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"flying"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final modifications
&lt;/h2&gt;

&lt;p&gt;To finish up, let's explore two more helpful tips. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reformatting the .json files we've already made&lt;/li&gt;
&lt;li&gt;An alternate way to pipe output to a file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use Vim to modify the .json files.  &lt;/p&gt;

&lt;p&gt;Don't worry, I'll help you get out.  Or, you can just purchase a book like this...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.redd.it%2F6lu41ha1o2461.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.redd.it%2F6lu41ha1o2461.jpg" width="800" height="1049"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the following command to start editing the charizard.json file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vim charizard.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to enter the &lt;code&gt;command mode&lt;/code&gt;.  You can do so by typing the colon key &lt;code&gt;:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now your cursor should be at the bottom.  Enter the following command.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note, you can only use this if you have JQ installed.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;%&lt;span class="p"&gt;!&lt;/span&gt;jq &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit return and the file should instantly reformat itself!&lt;/p&gt;

&lt;p&gt;Now type colon again and the following command to save and exit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;wq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit return, and you're successfully exited vim.  Congratulations!&lt;/p&gt;

&lt;p&gt;Now if you &lt;code&gt;cat&lt;/code&gt; the charizard.json file, it should be formatted correctly.  You can also trim down the file with a vim command like the following.  This will remove all excess data from the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;%&lt;span class="p"&gt;!&lt;/span&gt;jq &lt;span class="s1"&gt;'{name, id, types: [.types[].type.name]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you don't want reformat or trim down file in the first place, instead we'll trim and format the data before writing to a file.&lt;/p&gt;

&lt;p&gt;In order to do this, we can't use curl's &lt;code&gt;-o&lt;/code&gt; option.  We need to first pipe the response to JQ for formatting, then pipe that output to a file.&lt;/p&gt;

&lt;p&gt;Here's how it's done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Notice, we're using the &lt;code&gt;\&lt;/code&gt; to put our command on multiple lines&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://pokeapi.co/api/v2/pokemon/lapras | &lt;span class="se"&gt;\&lt;/span&gt;
    jq &lt;span class="o"&gt;{&lt;/span&gt;name, &lt;span class="nb"&gt;id&lt;/span&gt;, types: &lt;span class="o"&gt;[&lt;/span&gt;.types[].type.name]&lt;span class="o"&gt;}&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lapras.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the lapras.json file will have the formatted and scoped content sent to it by JQ.  To do that, we just use the &lt;code&gt;&amp;gt;&lt;/code&gt; key followed by the name of a file.&lt;/p&gt;

</description>
      <category>zsh</category>
      <category>curl</category>
      <category>http</category>
      <category>bash</category>
    </item>
    <item>
      <title>A Beginner's Guide to Curl: Part 3 - Seeing the Details</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sat, 04 Mar 2023 16:41:15 +0000</pubDate>
      <link>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-3-1lbc</link>
      <guid>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-3-1lbc</guid>
      <description>&lt;p&gt;In the previous article we learned about the &lt;code&gt;-o&lt;/code&gt; or &lt;code&gt;--output&lt;/code&gt; flag (or option).  Now we will explore the &lt;code&gt;-v&lt;/code&gt; flag which stand for &lt;code&gt;--verbose&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we want to see all the verbose details of our request and response, we need to pass in the &lt;code&gt;-v&lt;/code&gt; flag.  The particular option takes no arguments.  It's like a boolean, it's either on or off.&lt;/p&gt;

&lt;p&gt;Now we'll see what's going on "under the hood" as the manual states.  Try the following command in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; http://www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The top what what was printed to your STDOUT should look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt; Trying 2606:2800:220:1:248:1893:25c8:1946:80...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to www.example.com &lt;span class="o"&gt;(&lt;/span&gt;2606:2800:220:1:248:1893:25c8:1946&lt;span class="o"&gt;)&lt;/span&gt; port 80 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: www.example.com
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.85.0
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lines that begin with an asterisk are helpful messages curl is telling us.  The lines that begin with an angle bracket are the actual HTTP request/response details.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Request
&lt;/h2&gt;

&lt;p&gt;These are the details of the HTTP request you just made.&lt;/p&gt;

&lt;p&gt;Let's break it down line by line.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You attempted to connect to the IP address 2606:2800...  This is the full Internet Protocol Version 6 address which we referred to by the domain name &lt;code&gt;example.com&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next we see that we successfully connected at port #80&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This particular request method was a 'GET' request via the HTTP version 1 protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The host domain name we specified in our command&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An HTTP &lt;code&gt;header&lt;/code&gt; we sent, being our &lt;code&gt;User-Agent&lt;/code&gt; which is of course curl.  7.85.0 is my specific version.  Yours may be different.  You can see your version of curl by typing &lt;code&gt;$ curl -V&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, another HTTP &lt;code&gt;header&lt;/code&gt; we sent, being the &lt;code&gt;Accept&lt;/code&gt; header which specifies what type of content (MIME type) we are willing to accept in response.  It this case, everything! &lt;code&gt;*/*&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Response
&lt;/h2&gt;

&lt;p&gt;Here are the details of the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt; Mark bundle as not supporting multiuse
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Age: 266872
&amp;lt; Cache-Control: max-age&lt;span class="o"&gt;=&lt;/span&gt;604800
&amp;lt; Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF-8
&amp;lt; Date: Sat, 04 Mar 2023 16:21:04 GMT
&amp;lt; Etag: &lt;span class="s2"&gt;"3147526947+ident"&lt;/span&gt;
&amp;lt; Expires: Sat, 11 Mar 2023 16:21:04 GMT
&amp;lt; Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
&amp;lt; Server: ECS &lt;span class="o"&gt;(&lt;/span&gt;cha/8094&lt;span class="o"&gt;)&lt;/span&gt;
&amp;lt; Vary: Accept-Encoding
&amp;lt; X-Cache: HIT
&amp;lt; Content-Length: 1256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;* Mark bundle as not supporting multiuse&lt;/code&gt;.  This message appears because in this case we are using HTTP version 1 which does not support multiplexing or multiuse.  HTTP 2 does.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The version of HTTP and the response status code.  In this case, it's successful. 200! OK!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rest of the lines contain all the response headers sent back from example.com.  If you're interested, you can find information about all HTTP headers at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to look up specific curl options
&lt;/h2&gt;

&lt;p&gt;One of the difficulties you will undoubtedly face when leaning curl is finding the right option from the manual.  Let's say you want to learn about the &lt;code&gt;--verbose&lt;/code&gt; or &lt;code&gt;--output&lt;/code&gt; flags but you don't feel like scrolling through the manual to find them.  You can search the manual with &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We are going to "pipe" the output of the manual into the &lt;code&gt;grep&lt;/code&gt; utility.  Grep is basically a searching tool.  Try this command and then I'll explain what it's doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;man curl | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-B&lt;/span&gt; 5 &lt;span class="nt"&gt;-A&lt;/span&gt; 25 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'-v, --verbose'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we used the vertical bar character or "pipe" to pipe the output of &lt;code&gt;man curl&lt;/code&gt; into the &lt;code&gt;grep&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Grep takes an expression to search for. That's why we passed the &lt;code&gt;-e&lt;/code&gt; flag with the argument &lt;code&gt;-v, --verbose&lt;/code&gt;.  We are searching for that expression in the curl manual. Grep will return all the places where that specific string occurs.  There should be only one.&lt;/p&gt;

&lt;p&gt;However, before the &lt;code&gt;-e&lt;/code&gt; flag, we passed in two other flags and arguments: &lt;code&gt;-B&lt;/code&gt; with argument &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;-A&lt;/code&gt; with argument &lt;code&gt;25&lt;/code&gt;.  That means we want to print out 5 lines &lt;code&gt;before&lt;/code&gt; the expression occurs and 25 lines &lt;code&gt;after&lt;/code&gt; the expressing occurs.&lt;/p&gt;

&lt;p&gt;Use can use this piping trick to search for specific commands in the curl manual.&lt;/p&gt;

&lt;p&gt;Ready to go more in depth?  Read &lt;a href="https://dev.to/jvon1904/a-beginners-guide-to-curl-part-4-2ilg"&gt;A Beginner's Guide to Curl: Part 4&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>recommendations</category>
    </item>
    <item>
      <title>A Beginner's Guide to Curl: Part 1 - Your First Curl</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sat, 04 Mar 2023 16:01:53 +0000</pubDate>
      <link>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-1-4j4j</link>
      <guid>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-1-4j4j</guid>
      <description>&lt;p&gt;Curl (client-URL) is a command line utility app.  In the same way your web browser accesses online resources via the address bar, so curl does the same via the a command line interface.&lt;/p&gt;

&lt;p&gt;For example, open a new tab and go to this website, &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;. You probably saw a very boring looking example webpage.  If you inspect the HTML in your browser, you'll see it's the standard &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; with some &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags.  That's because the remote server behind this domain name serves HTML back when any client makes a GET request to that specific url.  Your browser is able present the HTML visually to you.&lt;/p&gt;

&lt;p&gt;Now, do the same thing in your terminal or command prompt.  Type the following command and hit return.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't worry about typing the "$".  That just shows this is a shell command we're typing.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have received several lines of text as a response.  In the exact same way that example.com returned HTML to your web browser, it returned the same response to your command line client.  You successfully just consumed a server response by using a terminal client &lt;em&gt;instead&lt;/em&gt; of a browser.  &lt;/p&gt;

&lt;p&gt;Curl is very powerful, because you can work with server requests and responses directly without a browser getting in your way.&lt;/p&gt;

&lt;p&gt;If you've ever used a tool like Postman for working with APIs, you'll find that curl can do almost all the same things if you know how to use it.&lt;/p&gt;

&lt;p&gt;Curl is very simple.  You type the word &lt;code&gt;curl&lt;/code&gt; followed by an address (URL).  Hit return and you get a response!&lt;/p&gt;

&lt;p&gt;That's not all!  You can customize your command with many different options and flags.  Each one accomplishes a specific purpose.  You could spend months or years trying to master all the different functionalities of curl.  &lt;/p&gt;

&lt;p&gt;Are you ready?  Let's get started in my next article, &lt;a href="https://dev.to/jvon1904/a-beginners-guide-to-curl-part-2-2dko"&gt;A Beginner's Guide to Curl: Part 2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>zsh</category>
      <category>linux</category>
      <category>http</category>
    </item>
    <item>
      <title>A Beginner's Guide to Curl: Part 2 - Options</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sat, 04 Mar 2023 16:00:31 +0000</pubDate>
      <link>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-2-2dko</link>
      <guid>https://dev.to/avocoaster/a-beginners-guide-to-curl-part-2-2dko</guid>
      <description>&lt;p&gt;If you want to teach yourself how to use curl, the best resource is the manual.&lt;/p&gt;

&lt;p&gt;Type the following command in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;man curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;man&lt;/code&gt; command is used to read the manual for other command line utilities (like curl).  To exit the manual, just type &lt;code&gt;q&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should see a brief synopsis of what curl is and what it does. As you can see, there are a lot more protocols than just &lt;code&gt;http&lt;/code&gt;.  For this guide we will only be using &lt;code&gt;http&lt;/code&gt; since that's what the internet is built off of.&lt;/p&gt;

&lt;p&gt;If you scroll down in the manual, you'll see a section titled "OUTPUT".  By default, curl will print the response to your STDOUT (standard output or terminal screen).&lt;/p&gt;

&lt;p&gt;For example, exit the manual by typing &lt;code&gt;q&lt;/code&gt;, and type the following in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the HTML response printed below to your STDOUT.  That's the default response when using curl. Now let's change that by adding an &lt;code&gt;option&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our first option will be the &lt;code&gt;-o&lt;/code&gt; flag or its longer full version &lt;code&gt;--output&lt;/code&gt;.  Whenever you pass an option to curl, you can specify it with a short name (with one dash) or a full name (with two dashes).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-o&lt;/code&gt; or &lt;code&gt;--output&lt;/code&gt; option takes one argument, the name of the file you want to write to.  This can be an existing file, or one that you haven't created yet.&lt;/p&gt;

&lt;p&gt;Let's try it out! Type the following command.  Notice we are changing our URL now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--output&lt;/span&gt; three_sentences.txt http://metaphorpsum.com/sentences/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things just happened.  First, curl created the file you specified in your current directory.  Second, curl wrote the response from the sever to that file.&lt;/p&gt;

&lt;p&gt;If you edit the file, you'll see the response is there.  Another way to see the contents is to &lt;code&gt;cat&lt;/code&gt; the file, you'll see the contents of the file printed to your STDOUT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;three_sentences.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you were to type the same command without the &lt;code&gt;--output&lt;/code&gt; option and file name, what do you think would happen?&lt;/p&gt;

&lt;p&gt;In the next article, we'll learn how to see more details contained in the request and response. &lt;a href="https://dev.to/jvon1904/a-beginners-guide-to-curl-part-3-1lbc"&gt;A Beginner's Guide to Curl: Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way, here are some other URLs you can try.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://metaphorpsum/com/sentences/10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://metaphorpsum/com/paragraphs/3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://metaphorpsum/com/paragraphs/3/2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>zsh</category>
      <category>bash</category>
      <category>http</category>
    </item>
    <item>
      <title>How fast is your ruby code?</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Mon, 07 Nov 2022 02:24:34 +0000</pubDate>
      <link>https://dev.to/avocoaster/how-fast-is-your-ruby-code-41o6</link>
      <guid>https://dev.to/avocoaster/how-fast-is-your-ruby-code-41o6</guid>
      <description>&lt;p&gt;Sometimes you might need a way to measure the time it takes your code to execute.&lt;/p&gt;

&lt;h2&gt;
  
  
  This works...
&lt;/h2&gt;

&lt;p&gt;Throw in a good old &lt;code&gt;Time.now&lt;/code&gt; and then subtract the time start time from the new &lt;code&gt;Time.now&lt;/code&gt; after the code executes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# let's see how long it takes the Ruby interpreter&lt;/span&gt;
&lt;span class="c1"&gt;# to string together 5 million integers.&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;string_together_ten_million_integers&lt;/span&gt;
  &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;

  &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;

  &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Took &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds to execute"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For me, this takes around 1.7 seconds on average.  Is yours similar?  &lt;/p&gt;

&lt;p&gt;Now, we can change things up and see if there are faster solutions. For instance, what if you convert the integers to String before you join?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# convert the integers to String before the join&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmm... 🤔 now it's more like 1.3 seconds.  Making that change seemed to shave off half a second.&lt;/p&gt;

&lt;p&gt;But wouldn't it make more sense to just instantiate a mutable String to push integers into?  Then, there is no need to join.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# instantiate a String instead of an array&lt;/span&gt;
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which one is the fastest for you?&lt;/p&gt;

&lt;p&gt;It's getting harder to keep track of all our results! Wouldn't it be great to see these methods profiled all at once and see the results neatly printed together?&lt;/p&gt;

&lt;p&gt;That's where the Ruby &lt;code&gt;Benchmark&lt;/code&gt; class comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is better...
&lt;/h2&gt;

&lt;p&gt;Benchmark is part of the Ruby standard library, meaning that it's readily available to require and use.  Just type &lt;code&gt;require 'benchmark'&lt;/code&gt; at the top of your file or any time during your IRB session.&lt;/p&gt;

&lt;p&gt;You can also type &lt;code&gt;irb -r benchmark&lt;/code&gt; when you start up your IRB session.&lt;/p&gt;

&lt;p&gt;Like every module in the Ruby StdLib you can find the documentation at &lt;a href="https://ruby-doc.org/stdlib-2.5.3/libdoc/benchmark/rdoc/Benchmark.html" rel="noopener noreferrer"&gt;ruby-doc.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The simplest way to use Benchmark is to send it the class method &lt;code&gt;::measure&lt;/code&gt; and provide a block of code as the argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# block of code to measure&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try inserting some of the above methods into the Benchmark block and see what the resulting times are.&lt;/p&gt;

&lt;p&gt;You're going to see the return value as a &lt;code&gt;Benchmark::Tms&lt;/code&gt; class with the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cstime - children system CPU time&lt;/li&gt;
&lt;li&gt;cutime - children user CPU time&lt;/li&gt;
&lt;li&gt;stime - system CPU time&lt;/li&gt;
&lt;li&gt;utime - user CPU time&lt;/li&gt;
&lt;li&gt;total - cstime + cutime + stime + utime &lt;/li&gt;
&lt;li&gt;real - total elapsed time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now for a little explanation of these terms.  The user time is how long it actually takes for your code to execute.  The system time is the underlying system underneath your code to do what it needs to do (your computer's kernel, etc.).  The total time is the addition of the system and the user times.  &lt;/p&gt;

&lt;p&gt;So what is the real time?  That's adding in user input, network connections, etc.  If you only care about the actual wall clock time from start to finish, just look at the real time.&lt;/p&gt;

&lt;p&gt;The children system and user times would be for any other methods called within your block.  These would be child processes.&lt;/p&gt;

&lt;p&gt;Although using &lt;code&gt;Benchmark::measure&lt;/code&gt; is a good way to measure the run time for one block of code, there is a way to measure different blocks side by side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best way...
&lt;/h2&gt;

&lt;p&gt;Instead of &lt;code&gt;::measure&lt;/code&gt;, let's use the &lt;code&gt;::bm&lt;/code&gt; method. This method allows you to generate reports of multiple code blocks.  Perfect!  Let's use this with our three methods above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way, in Ruby we use '#' before instance method names and '::' before class method names when we refer to them. Since we never have to call &lt;code&gt;Benchmark.new&lt;/code&gt;, we use the class methods only.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'benchmark'&lt;/span&gt;

&lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bm&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"array/join"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt; 
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"array/to_s/join"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"string/to_s"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did the results that printed to your console align correctly?  With longer labels we need to adjust the &lt;code&gt;label_width&lt;/code&gt; of the results.  It's actually the first argument to the &lt;code&gt;::bm&lt;/code&gt; method, so try &lt;code&gt;Benchmark.bm(20) do |x|&lt;/code&gt; to spread out the results.&lt;/p&gt;

&lt;p&gt;These are the results on my machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                           user     system      total        real
array/join             1.551520   0.168228   1.719748 (  1.789678)
array/to_s/join        1.209965   0.122323   1.332288 (  1.373220)
string/to_s            0.893824   0.047670   0.941494 (  0.949304)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully you are feeling empowered to profile your Ruby code with the Benchmark utility!&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced additional content
&lt;/h2&gt;

&lt;p&gt;One way to challenge your understanding of the Ruby Standard Library is to peruse through the source code.  You'll find that it's not as intimidating as you might think.  &lt;/p&gt;

&lt;p&gt;Don't feel pressure to understand it all at first glance.  Feel encouraged that you understand any of it and with practice your understanding will grow and grow!&lt;/p&gt;

&lt;p&gt;Where can you find it?  I use RVM (Ruby Version Manager) to manage and install my rubies and gems.  So for me, I have a .rvm directory in my home directory. This is where the Standard Library is housed.&lt;/p&gt;

&lt;p&gt;For me its &lt;code&gt;~/.rvm/rubies/ruby-3.0.0/lib/ruby/3.0.0&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;From there you can open open up the benchmark.rb file and see the source code.  It's a small module (written over 20 years ago!) of just over 500 lines with much of that taken up with documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;p&gt;I first noted the different parameters the various methods received.  This helped me to understand how I could use the methods.  &lt;/p&gt;

&lt;p&gt;I wanted my reports to have a longer width. I saw that the &lt;code&gt;Report&lt;/code&gt; class was instantiated with a &lt;code&gt;width&lt;/code&gt; attribute from the &lt;code&gt;::benchmark&lt;/code&gt; method which is called from the &lt;code&gt;::bm&lt;/code&gt; method.  That's how I learned I could call &lt;code&gt;::bm&lt;/code&gt; with '20' as the argument to spread out the report.&lt;/p&gt;

&lt;p&gt;Another interesting note is that the magic of Benchmark really happens in the &lt;code&gt;::measure&lt;/code&gt; method on line 291.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# :yield:&lt;/span&gt;
    &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Tms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utime&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stime&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cutime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cutime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cstime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cstime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like we were inserting &lt;code&gt;Time.now&lt;/code&gt; in our original code, that's really all Benchmark does. Only, it uses a more sophisticated approach, &lt;code&gt;Process.times&lt;/code&gt; and &lt;code&gt;Process.clock_gettime()&lt;/code&gt;.  Then it yields the block of code supplied and calls the same Process methods again and does the subtraction.  This almost exactly what we were doing.&lt;/p&gt;

&lt;p&gt;Apparently it isn't magic, just good Ruby developers like you and me writing simple code. 👊&lt;/p&gt;

&lt;p&gt;If you were to do a little more digging in the the Ruby &lt;code&gt;Process&lt;/code&gt; you might be able to develop your own customized Benchmark module.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>tutorial</category>
      <category>benchmark</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Turn a Ruby file into an executable command!</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Tue, 01 Nov 2022 04:01:34 +0000</pubDate>
      <link>https://dev.to/avocoaster/turn-a-ruby-file-into-an-executable-command-39of</link>
      <guid>https://dev.to/avocoaster/turn-a-ruby-file-into-an-executable-command-39of</guid>
      <description>&lt;p&gt;Don't have 20 minutes to watch? Read the 6 minute article &lt;a href="https://dev.to/jvon1904/how-to-create-a-ruby-executable-j70"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Learn how to create a Ruby executable</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Mon, 31 Oct 2022 02:42:23 +0000</pubDate>
      <link>https://dev.to/avocoaster/how-to-create-a-ruby-executable-j70</link>
      <guid>https://dev.to/avocoaster/how-to-create-a-ruby-executable-j70</guid>
      <description>&lt;p&gt;Don't like reading?  Watch the video &lt;a href="https://dev.to/jvon1904/turn-a-ruby-file-into-an-executable-command-39of"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have Ruby installed on your computer, we know that you can execute &lt;code&gt;.rb&lt;/code&gt; files with the &lt;code&gt;ruby &amp;lt;file name&amp;gt;.rb&lt;/code&gt; command.  This is &lt;u&gt;not&lt;/u&gt; what we are talking about in this article.&lt;/p&gt;

&lt;p&gt;This article is about executing ruby programs without typing &lt;code&gt;ruby&lt;/code&gt;, &lt;code&gt;./&lt;/code&gt;, or an &lt;code&gt;.rb&lt;/code&gt; extension and being able to execute the command from anywhere in your file system.&lt;/p&gt;

&lt;p&gt;Just like when you type &lt;code&gt;gem&lt;/code&gt;, &lt;code&gt;rails&lt;/code&gt;, or &lt;code&gt;irb&lt;/code&gt;, and your console immediately recognizes and runs a program, we want to do this with our own custom-built Ruby file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the program
&lt;/h2&gt;

&lt;p&gt;Create a new directory anywhere.  Name it &lt;code&gt;favorite_color&lt;/code&gt;.  This new Ruby program is going to do one thing, tell us our favorite color.  &lt;/p&gt;

&lt;p&gt;Make two sub-directories inside &lt;code&gt;favorite_color&lt;/code&gt;. Name them &lt;code&gt;lib&lt;/code&gt;, and &lt;code&gt;bin&lt;/code&gt;.  The lib directory will house the logic of the program.  The bin directory will house the executable file that requires and calls the program in lib.&lt;/p&gt;

&lt;p&gt;By the way, 'lib' stands for 'library', and 'bin' stands for 'binaries' (executable files).  You could also name the bin folder 'exe' for 'executables.  Housing your program source code in &lt;code&gt;lib&lt;/code&gt; and your executable in &lt;code&gt;bin&lt;/code&gt; or &lt;code&gt;exe&lt;/code&gt; is standard for Ruby gem packages.&lt;/p&gt;

&lt;p&gt;Name the lib file &lt;code&gt;favorite_color.rb&lt;/code&gt;, and name the bin file &lt;code&gt;fav-color.rb&lt;/code&gt;. (We will eventually remove the &lt;code&gt;.rb&lt;/code&gt; extension.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; favorite_color/&lt;span class="o"&gt;{&lt;/span&gt;lib,bin&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;favorite_color/lib/favorite_color.rb favorite_color/bin/fav-color.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your file tree should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;favorite_color
├── bin
│   └── fav-color.rb
└── lib
    └── favorite_color.rb

2 directories, 2 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, add some logic to &lt;code&gt;favorite_color.rb&lt;/code&gt;.  Here's what my class will look like.  Write this however you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FavoriteColor&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt;     &lt;span class="vi"&gt;@color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;declaration&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;     &lt;span class="s2"&gt;"Your favorite color is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;declare&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;     &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;declaration&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
 &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The executable file inside the &lt;code&gt;bin&lt;/code&gt; directory is responsible for loading the FavoriteColor class, initializing it, and calling it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"../lib/favorite_color.rb"&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;favorite_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FavoriteColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"teal"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#insert your real favorite color.&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;favorite_color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;declare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, if you &lt;code&gt;cd&lt;/code&gt; into &lt;code&gt;bin&lt;/code&gt; you can execute the &lt;code&gt;fav-color.rb&lt;/code&gt; file like you normally would and it should print the output to your console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruby fav-color.rb
Your favorite color is teal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we could implement functionality in &lt;code&gt;fav-color.rb&lt;/code&gt; to read an argument passed in which sets the color of the class, but for now we only want to focus on making this file a true executable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the shebang
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;shebang&lt;/em&gt; refers to the characters &lt;code&gt;#!&lt;/code&gt;.  It's the prefix used when referencing the path to the interpreter that the shell should use to execute a script from the terminal. For instance, if you look at some of the executables in your &lt;code&gt;/bin&lt;/code&gt; directories that are written in shell scripts, you will see &lt;code&gt;#!/bin/sh&lt;/code&gt; at the top, or something similar.  For Ruby scripts, you should reference &lt;code&gt;/usr/bin/env&lt;/code&gt;.  Why is that?  Because the &lt;code&gt;env&lt;/code&gt; command here is going to search for the first &lt;code&gt;ruby&lt;/code&gt; interpreter in your &lt;code&gt;PATH&lt;/code&gt;.  The full line will look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be able to just add &lt;code&gt;#! ruby&lt;/code&gt; or &lt;code&gt;#!/usr/bin/ruby&lt;/code&gt;, but the safest way is to do the full reference so that the executable will work on the maximum amount of machines.&lt;/p&gt;

&lt;p&gt;At this point, your &lt;code&gt;fav-color.rb&lt;/code&gt; file should look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"../lib/favorite_color.rb"&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;favorite_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FavoriteColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;favorite_color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;declare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, go ahead and try to execute the file.  (Hint: at this point, with the shebang line, it is a true executable). You can still use the &lt;code&gt;ruby&lt;/code&gt; command, but in order to take advantage of the shebang you need to type &lt;code&gt;./&amp;lt;file-name&amp;gt;&lt;/code&gt;.  Did it work?&lt;/p&gt;

&lt;p&gt;Most likely not. You probably don't have permission to execute the file.  Each file on your machine has permissions set for reading ('r'), writing ('w'), and executing ('x').  When you first create a file, it defaults to allow you as the creator to read and write to it, and others to read it.  In order to see those permissions, you need to use the shell commands &lt;code&gt;ls -l&lt;/code&gt;, the &lt;code&gt;-l&lt;/code&gt; flag standing for &lt;code&gt;long format&lt;/code&gt;.  If you use ZSH, you can simply type the shortcut to this which is &lt;code&gt;ll&lt;/code&gt;.  You should see something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;total 8
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 jvon1904  staff   132B Oct 30 20:47 fav-color
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;total 8&lt;/code&gt; refers to the total size of the directory in kilobytes.&lt;/p&gt;

&lt;p&gt;On the second line, first column, you see &lt;code&gt;-rw-r--r--&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Although cryptic at first, this is a very simple designation for the file permissions.  &lt;/p&gt;

&lt;p&gt;The first character is either &lt;code&gt;-&lt;/code&gt; meaning it's a file. It could also be &lt;code&gt;d&lt;/code&gt; for directory.  &lt;/p&gt;

&lt;p&gt;The next three characters are permissions for the owner, which in this case are &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;write&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;The fourth character is the slot for &lt;code&gt;execute&lt;/code&gt;, &lt;code&gt;x&lt;/code&gt;.  If the owner could execute the file, it would be &lt;code&gt;-rwx-r--r--&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;The 5th-7th characters are for the group, which on my computer is called 'staff', and the 8th-10th characters are for others.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Changing the permissions for the file
&lt;/h2&gt;

&lt;p&gt;In order to change the permissions, you need to use the &lt;code&gt;chmod&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;The most straightforward way to add user permissions is to type &lt;code&gt;chmod&lt;/code&gt; followed by a letter representing who is receiving the permission (&lt;code&gt;u&lt;/code&gt;, the user/owner, &lt;code&gt;g&lt;/code&gt;, the group, &lt;code&gt;o&lt;/code&gt; others, or &lt;code&gt;a&lt;/code&gt; all) followed by a &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt; (adding/removing permissions) followed by the permission (&lt;code&gt;r&lt;/code&gt;, &lt;code&gt;w&lt;/code&gt;, or &lt;code&gt;x&lt;/code&gt;) and finally the file name. &lt;/p&gt;

&lt;p&gt;For us it would look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x fav-color
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
total 8
&lt;span class="nt"&gt;-rwxr--r--&lt;/span&gt;  1 jvon1904  staff  132 Oct 30 21:00 fav-color
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There happens to be another fantastic way to set all permissions for all people with only three numbers!  For instance, if you want all people to have all permissions, you would type &lt;code&gt;chmod 777 &amp;lt;file-name&amp;gt;&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;If you type &lt;code&gt;000&lt;/code&gt; you will remove all permissions completely.  Can you figure out why?&lt;/p&gt;

&lt;p&gt;The three numbers represent the three entities being permitted (u, g, and o).&lt;/p&gt;

&lt;p&gt;0 -&amp;gt; no permissions&lt;/p&gt;

&lt;p&gt;1 -&amp;gt; execute permission&lt;/p&gt;

&lt;p&gt;2 -&amp;gt; write permission&lt;/p&gt;

&lt;p&gt;4 -&amp;gt; read permission&lt;/p&gt;

&lt;p&gt;Then add up those numbers for any combination of the three.  So a 7 means all three permissions because 7 = 1 + 2 + 4.  Cool right?! &lt;/p&gt;

&lt;p&gt;In our case, you could type &lt;code&gt;chmod 744 fav-color.rb&lt;/code&gt; and nothing should change.&lt;/p&gt;

&lt;p&gt;Now that we've changed the permissions, try executing the file like &lt;code&gt;./fav-color.rb&lt;/code&gt; and it should work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the executable to your path
&lt;/h2&gt;

&lt;p&gt;At this point, we should go ahead and take off the &lt;code&gt;.rb&lt;/code&gt; extension because it's not needed now that we've added our shebang directive and turned the file into an executable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;fav-color.rb fav-color
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem now is that you must reference the entire path of the file in order to execute it.&lt;/p&gt;

&lt;p&gt;If you are inside the directory that contains &lt;code&gt;fav-color&lt;/code&gt; you must type &lt;code&gt;./&lt;/code&gt; before hand.  &lt;/p&gt;

&lt;p&gt;If you are inside the &lt;code&gt;favorite_color&lt;/code&gt; root directory, you must execute it as &lt;code&gt;bin/fav-color&lt;/code&gt;.  This is not ideal.  We want to be able to type &lt;code&gt;fav-color&lt;/code&gt; from anywhere.&lt;/p&gt;

&lt;p&gt;There are two ways to accomplish this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Exporting the full path to the executable to your &lt;code&gt;$PATH&lt;/code&gt; variable, or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding a link to the executable to one of your &lt;code&gt;/bin&lt;/code&gt; directories already loaded into the &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are familiar with adding to your PATH, feel free to use the first option (adding &lt;code&gt;export PATH=$PATH:path/to/favorite_color/bin&lt;/code&gt; to &lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.zprofile&lt;/code&gt; or &lt;code&gt;.bash_profile&lt;/code&gt;, etc.)&lt;/p&gt;

&lt;p&gt;The recommended option in this case is to make the executable a binary in one of your &lt;code&gt;bin&lt;/code&gt; directories.  &lt;/p&gt;

&lt;p&gt;You've probably noticed that when you venture underneath your HOME ~ directory, there are more than one 'bin' folder.&lt;/p&gt;

&lt;p&gt;In order to not confound system critical binaries, you should place a custom binary in &lt;code&gt;/usr/local/bin&lt;/code&gt;.  We can do this by linking the file to that directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; ~/favorite_colors/bin/fav-color /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the &lt;code&gt;ln&lt;/code&gt; (link) command, make sure to reference both the executable and the bin directory as abosolute paths.&lt;/p&gt;

&lt;p&gt;You can &lt;code&gt;cd&lt;/code&gt; into /usr/local/bin to make sure it's there.&lt;/p&gt;

&lt;p&gt;I have a line like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lrwxr-xr-x  1 root  wheel    44B Oct 30 22:26 fav-color -&amp;gt; /Users/jvon1904/favorite_color/bin/fav-color
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It appears that linking the file to /usr/local/bin automatically allows everyone to execute it.&lt;/p&gt;

&lt;p&gt;Give it a shot. Execute the file from anywhere in your file system simply as &lt;code&gt;fav-color&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>zsh</category>
      <category>ruby</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Wrap Around a Range of Numbers with the Modulo</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Thu, 12 May 2022 21:47:50 +0000</pubDate>
      <link>https://dev.to/avocoaster/how-to-wrap-around-a-range-of-numbers-with-the-modulo-cdo</link>
      <guid>https://dev.to/avocoaster/how-to-wrap-around-a-range-of-numbers-with-the-modulo-cdo</guid>
      <description>&lt;p&gt;&lt;em&gt;We'll be using JavaScript, but this should work for any language that uses the modulo operator&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Sometimes you have a range of numbers like 1-10.  You want functions to increment and decrement the index within the range without going below the minimum or above the maximum.  The modulo operator accomplishes this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;I was recently following along the guide to &lt;a href="https://stimulus.hotwired.dev/handbook/origin" rel="noopener noreferrer"&gt;Stimulus.js&lt;/a&gt; and ran across this problem.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're interested, Stimulus is a JavaScript framework that comes standard in Ruby on Rails 7.  Since I like to code in Ruby and use Rails, I've been learning it.  It allows you to easily manipulate DOM elements with Javascript by adding data attributes to your elements.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The guide walked through creating slideshow-like functionality where two buttons toggle through a list of four divs that either display or are hidden.&lt;/p&gt;

&lt;p&gt;The problem is that when the current index is 0, and you click previous, the index decrements to -1.  Similarly, if you are on index 3 (the fourth item in the list), the index increments to 5.  The desired behavior would be for it to wrap around to the first/last elements.&lt;/p&gt;

&lt;p&gt;increment&lt;br&gt;
0 → 1 → 2 → 3 → 0 → 1&lt;/p&gt;

&lt;p&gt;decrement &lt;br&gt;
2 ← 3 ← 0 ← 1 ← 2 ← 3 &lt;/p&gt;

&lt;p&gt;You get the idea!&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Accomplish this using Javascript!
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// let's start by defining a simple class Range &lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// here are our two methods.  We will return the index&lt;/span&gt;
  &lt;span class="c1"&gt;// so that it's easy to see what's happening&lt;/span&gt;
  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So the goal here would be to instantiate a new instance of Range, and use the two methods increment and decrement the index, looping through 0-4, never going below zero or above four.  Of course... this won't work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// our class allows us to specify the starting range.&lt;/span&gt;
&lt;span class="c1"&gt;// we could have set the default to 0 as well.&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try calling the methods and see what happens to the index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;// cool! it's works&lt;/span&gt;

&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="c1"&gt;// oops! too high!&lt;/span&gt;
&lt;span class="c1"&gt;// let's bring it down.&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;// oops!  too low!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So hopefully now what we are trying to accomplish is clear.  Now let's get to the solution. &lt;/p&gt;

&lt;h3&gt;
  
  
  Using the Modulo Operator
&lt;/h3&gt;

&lt;p&gt;What is it?  TL;DR it returns the remainder after division.&lt;/p&gt;

&lt;p&gt;3 divided by 2 is 1 with a remainder of 1.  What if we only want the remainder value?  Use our friend modulo.  It's just the percent sign.&lt;/p&gt;

&lt;p&gt;3   % 2   =&amp;gt; 1&lt;br&gt;
10  % 8   =&amp;gt; 2&lt;br&gt;
5   % 5   =&amp;gt; 0&lt;br&gt;
4   % 2   =&amp;gt; 0&lt;br&gt;
6   % 3   =&amp;gt; 0&lt;br&gt;
7   % 4   =&amp;gt; 3&lt;br&gt;
156 % 37  =&amp;gt; 8&lt;/p&gt;

&lt;p&gt;Whenever you use modulo with a larger number on the right, it will return the number on the left. &lt;/p&gt;

&lt;p&gt;1 % 10 =&amp;gt; 1&lt;br&gt;
1 % 2 =&amp;gt; 1&lt;br&gt;
5 % 6 =&amp;gt; 5&lt;br&gt;
5 % 10000 =&amp;gt; 5&lt;/p&gt;

&lt;p&gt;Modulo can actually accomplish some cool things!  I first saw a practical use for it while trying to code a 2D spaceship game in Ruby.  The modulo operator allowed the spaceship to go off the screen and re-enter from the other side.  It's going to serve a similar purpose here.&lt;/p&gt;

&lt;p&gt;Let's say my index is 0. I want to add 1 to it but not allow it to get above the number 4.  So 5 is the length of the range 0,1,2,3,4. &lt;/p&gt;

&lt;p&gt;So what I do is this, I assign the original index (0) to the sum of itself plus the range length (5) plus the increment amount (1) modulo the range length (5).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index = (index + rangeLength + incrementAmount) % rangeLength&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Mind blown yet?  🤯&lt;/p&gt;

&lt;p&gt;Try it out!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Assign the original index to the sum of itself plus the range length plus the increment &lt;u&gt;modulo&lt;/u&gt; the range length.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;Correction!&lt;/em&gt; When incrementing, you don't need to add the range length.  It doesn't hurt if you do though.  So you could just do index = (index + 1) % rangeLength.  You do need to add the range length when decrementing though.
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;index = 0&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (0 + 5 + 1) % 5 =&amp;gt; 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Six divided by five has a remainder of 1.  So now the index is 1.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index = (1 + 5 + 1) % 5 =&amp;gt; 2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (2 + 5 + 1) % 5 =&amp;gt; 3&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (3 + 5 + 1) % 5 =&amp;gt; 4&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (4 + 5 + 1) % 5 =&amp;gt; 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It worked!  Because 10 divided by 5 has no remainder the index now restarted at 0.&lt;/p&gt;

&lt;p&gt;Now let's try the decrement method.  Just assign the index to the remainder of itself plus the range length minus the decrement amount divided by the range length.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index = (index + rangeLength - decrementAmount) % rangeLength&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let index = 4&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (4 + 5 - 1) % 5 =&amp;gt; 3&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (3 + 5 - 1) % 5 =&amp;gt; 2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (2 + 5 - 1) % 5 =&amp;gt; 1&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (1 + 5 - 1) % 5 =&amp;gt; 0&lt;/code&gt;&lt;br&gt;
&lt;code&gt;index = (0 + 5 - 1) % 5 =&amp;gt; 4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we can edit our Range class to implement this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;incrementAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrementAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;incrementAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrementAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now test it out.  Our &lt;code&gt;next()&lt;/code&gt; and &lt;code&gt;previous()&lt;/code&gt; methods should work perfectly!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>modulo</category>
    </item>
    <item>
      <title>Using Nokogiri and RegEx to Scan a Webpage in Ruby</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Sat, 07 May 2022 01:59:21 +0000</pubDate>
      <link>https://dev.to/avocoaster/using-nokogiri-and-regex-to-scan-a-webpage-in-ruby-45l3</link>
      <guid>https://dev.to/avocoaster/using-nokogiri-and-regex-to-scan-a-webpage-in-ruby-45l3</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We are going to use a gem to search for a topic in a web article to produce a list of snippets.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://dev.to/jvon1904/what-is-nokogiri-48m4"&gt;this&lt;/a&gt; article I wrote to get an introduction to Nokogiri.&lt;/p&gt;

&lt;p&gt;I'm a casual fan of into baseball. ESPN has lots of MLB articles.  What do they talk about?  It's a mystery!  We need to scan the page with Nokogiri to find out.  Are you ready?&lt;/p&gt;

&lt;h2&gt;
  
  
  Get that Article!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;➜&lt;/span&gt;  &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="n"&gt;irb&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;simple&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nokogiri'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'open-uri'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="c1"&gt;# I'm going to scan the article at this URL.  Feel free to &lt;/span&gt;
&lt;span class="c1"&gt;# find one of your own, since this will probably be outdated &lt;/span&gt;
&lt;span class="c1"&gt;# by the time you read this.&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://www.espn.com/mlb/story/_/id/33855507/mlb-power-rankings-week-4
-new-team-surged-our-no-1-spot'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"https://www.espn.com/mlb/story/_/id/33855507/mlb-power-rankings-week-4-...
&amp;gt;&amp;gt; web_page = Nokogiri::HTML5(URI(url))
=&amp;gt;
#(Document:0x5b4 {
...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to find the body of this article so we only scan the relevant portions.  We'll use the &lt;code&gt;#css&lt;/code&gt; method with the div and class name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.article-body'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;Nokogiri::XML::Element:0x5730 name="div" attributes=[#&amp;lt;Nokogiri::XML:...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"7:00 AM ETESPNFacebookTwitterFacebook MessengerPinterestEmailprintFour ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the fun part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regular Expression Scan
&lt;/h2&gt;

&lt;p&gt;Ruby has a &lt;code&gt;String#scan&lt;/code&gt; method that takes a Regular Expression as an argument and returns an array of all occurrences.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt; "don't do that dog!".scan(/do/) =&amp;gt; ["do", "do", "do"]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But we don't really want to just get a list of occurrences.  We want to get the whole context so that we can see what the article is talking about. To accomplish this, we need to find the index of each occurrence as if our string was an array of characters. Then we will slice well before and after this index to get the context of each occurrence.  This brings up a (maybe lesser-known) method called &lt;code&gt;#to_enum&lt;/code&gt; (to enumerator).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;to_enum&lt;/code&gt; method allows us to enumerate the String and pass a method and optional argument.  Here's an example where we will get the byte code for each ASCII character in a string. We will print each to binary using &lt;code&gt;to_s(2)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"abcdefg"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_enum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:each_byte&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;"1100001"&lt;/span&gt;
&lt;span class="s2"&gt;"1100010"&lt;/span&gt;
&lt;span class="s2"&gt;"1100011"&lt;/span&gt;
&lt;span class="s2"&gt;"1100100"&lt;/span&gt;
&lt;span class="s2"&gt;"1100101"&lt;/span&gt;
&lt;span class="s2"&gt;"1100110"&lt;/span&gt;
&lt;span class="s2"&gt;"1100111"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our purposes, we will pass the &lt;code&gt;:scan&lt;/code&gt; method with the argument being our Regular Expression.  Then we will map each occurrence with &lt;code&gt;Regexp.last_match.begin(0)&lt;/code&gt; to get the beginning index for the occurrence.  This is how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# remember text holds the text of the article body&lt;/span&gt;
&lt;span class="c1"&gt;# each index will go into the indices variable&lt;/span&gt;
&lt;span class="c1"&gt;# we can search for whatever we want, let's search for pitch&lt;/span&gt;
&lt;span class="c1"&gt;# this will work for pitch, pitchers, pitches, etc.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_enum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:scan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/pitch/i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pitch&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
     &lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last_match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1825&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1825&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;3699&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;4727&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;10007&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;10127&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;10846&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;11016&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;12617&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;13734&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;14060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;14585&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;14927&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;16019&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;17835&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;18858&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great!  This list of indices reveals to us where to slice to get our data.  We'll slice 30 characters before the start and will will make the length of our slice 70 characters. We'll push these snippets of text into an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;snippets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;snippets&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;snippets&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"n-differential in the majors. Pitching has mostly carried them, but th"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"st year, Milwaukee's starting pitching was basically three deep. That "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"rt envious: Too many starting pitchers. Clevinger is the sixth member "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;" allowed. While he has a five-pitch repertoire, one thing he's done th"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"eup combo. He threw those two pitches a combined 64.3% of the time las"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"ause his swing rate and first-pitch swing rate in particular are up. H"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"nd him he's going to get more pitches to hit. -- Schoenfield17. Chicag"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"2 batting line this year. The pitching staff has been one of the brigh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"ice start. Good, right-handed pitching will stymie them this year, tho"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"le against both hard and soft pitching, despite dominating the league "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;" ranks among some of the best pitchers in all of baseball in WAR. -- L"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;" back to .500. Their starting pitchers have lifted them, with Zac Gall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;". The Rangers did have better pitching last week, moving them up the l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"r nine innings in 11⅓ innings pitched. -- Lee29. Washington NationalsR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;" Colorado will do that -- but pitching was a big problem. The Reds com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We did it!  Now let's clean them up so they start and end with full words. We'll take each snippet, split it apart by whitespace, remove the first and last partial words, then paste it back together with spaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;snippets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;snippet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"in the majors. Pitching has mostly carried them, but"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"year, Milwaukee's starting pitching was basically three deep."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"envious: Too many starting pitchers. Clevinger is the sixth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"While he has a five-pitch repertoire, one thing he's done"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"combo. He threw those two pitches a combined 64.3% of the time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"his swing rate and first-pitch swing rate in particular are up."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"him he's going to get more pitches to hit. -- Schoenfield17."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"batting line this year. The pitching staff has been one of the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"start. Good, right-handed pitching will stymie them this year,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"against both hard and soft pitching, despite dominating the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"among some of the best pitchers in all of baseball in WAR. --"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"to .500. Their starting pitchers have lifted them, with Zac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"The Rangers did have better pitching last week, moving them up the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"nine innings in 11⅓ innings pitched. -- Lee29. Washington"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;"will do that -- but pitching was a big problem. The Reds"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it!  Hopefully this article revealed just some of the cool features to Ruby.  Don't be afraid to explore new gems and look up new methods on the Ruby-Doc website.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>regex</category>
      <category>scraping</category>
      <category>nokogiri</category>
    </item>
    <item>
      <title>What is Nokogiri?</title>
      <dc:creator>Jesse vonBergen</dc:creator>
      <pubDate>Thu, 05 May 2022 01:44:22 +0000</pubDate>
      <link>https://dev.to/avocoaster/what-is-nokogiri-48m4</link>
      <guid>https://dev.to/avocoaster/what-is-nokogiri-48m4</guid>
      <description>&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;A Nokogiri is a Japanese pull saw.  Oh... didn't help?  Keep reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gem
&lt;/h2&gt;

&lt;p&gt;Nokogiri comes standard in the Gemfiles of Rails apps.  I first noticed it because it showed up in a Bundler error. &lt;/p&gt;

&lt;p&gt;Nokogiri is a low-dependency module written in C, Java, and Ruby that parses XML and HTML so that these protocols can be used by Ruby.  Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Nokogiri to Parse HTML
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do you want to use Ruby to extract data from a webpage?
&lt;/h3&gt;

&lt;p&gt;First run &lt;code&gt;nokogiri -v&lt;/code&gt; and see if you get a response with a verion number.  If not, you'll have to run &lt;code&gt;gem i nokogiri&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  ~ irb --simple-prompt
&amp;gt;&amp;gt; require 'nokogiri'
=&amp;gt; true
&amp;gt;&amp;gt; Nokogiri
=&amp;gt; Nokogiri
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to require it, otherwise you'll get a NameError for an uninitialized constant.  &lt;/p&gt;

&lt;p&gt;First, we will start by parsing HTML we create, then we will parse an actual webpage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# First, put some valid html into a string.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;section&amp;gt;&amp;lt;h2&amp;gt;A List of Stuff&amp;lt;/h2&amp;gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Camera&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Computer&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Television&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&amp;lt;/section&amp;gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# Now pass that string into the HTML5 module as an argument&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a response like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#(Document:0x4c4 {&lt;/span&gt;
  &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;#(Element:0x4d8 {&lt;/span&gt;
      &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;#(Element:0x4ec { name = "head" }),&lt;/span&gt;
        &lt;span class="c1"&gt;#(Element:0x500 {&lt;/span&gt;
          &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;#(Element:0x514 {&lt;/span&gt;
              &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;#(Text "Hello World!")]&lt;/span&gt;
              &lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="c1"&gt;#(Element:0x528 {&lt;/span&gt;
              &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"section"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="c1"&gt;#(Element:0x53c {&lt;/span&gt;
                  &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"h2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;#(Text "A List of Stuff")]&lt;/span&gt;
                  &lt;span class="p"&gt;}),&lt;/span&gt;
                &lt;span class="c1"&gt;#(Element:0x550 {&lt;/span&gt;
                  &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="c1"&gt;#(Element:0x564 {&lt;/span&gt;
                      &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"li"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;#(Text "Camera")]&lt;/span&gt;
                      &lt;span class="p"&gt;}),&lt;/span&gt;
                    &lt;span class="c1"&gt;#(Element:0x578 {&lt;/span&gt;
                      &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"li"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;#(Text "Computer")]&lt;/span&gt;
                      &lt;span class="p"&gt;}),&lt;/span&gt;
                    &lt;span class="c1"&gt;#(Element:0x58c {&lt;/span&gt;
                      &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"li"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;#(Text "Television")]&lt;/span&gt;
                      &lt;span class="p"&gt;})]&lt;/span&gt;
                  &lt;span class="p"&gt;})]&lt;/span&gt;
              &lt;span class="p"&gt;})]&lt;/span&gt;
          &lt;span class="p"&gt;})]&lt;/span&gt;
      &lt;span class="p"&gt;})]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nokogiri's HTML5 module took our HTML string and returned a Document class to us that has it's own set of methods.  Let's look at a couple. (Remember you can always list all the methods by using &lt;code&gt;Document.methods.sort&lt;/code&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Document#children
&lt;/h2&gt;

&lt;p&gt;This will will return an array-like &lt;code&gt;XML::NodeSet&lt;/code&gt;.  It only has a length of one because it's the &lt;code&gt;&amp;lt;html&amp;gt;...&amp;lt;/html&amp;gt;&lt;/code&gt; element that we never included in our string.  This child has two children, the &lt;code&gt;&amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;&lt;/code&gt; and the &lt;code&gt;&amp;lt;body&amp;gt;...&amp;lt;/body&amp;gt;&lt;/code&gt; tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#(Element:0x80c {&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ul&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;Nokogiri::XML::Text:0x8c0 "A List of Stuff"&amp;gt;, #&amp;lt;Nokogiri::XML::Elemen...&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;Nokogiri::XML::Text:0x8c0 "A List of Stuff"&amp;gt;, #&amp;lt;Nokogiri::XML::Elemen..&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="sc"&gt;?&amp;gt;&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Camera&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Computer&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Television&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parsing HTML from the Internet
&lt;/h2&gt;

&lt;p&gt;I've heard the Internet is a good place to find HTML documents to parse.  You can capture some of this HTML by using the Client URL command in your terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://ruby-doc.org" rel="noopener noreferrer"&gt;Ruby-Doc.org&lt;/a&gt; is a great resource to learn about all Ruby objects.
&lt;/h3&gt;

&lt;p&gt;Capture it like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  ~ curl 'https://ruby-doc.org'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's cool to see the HTML populate the terminal, it's even better when it comes back as a Ruby object for us to use the data.  To do so, let's use Nokogiri!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# You'll need the open-uri gem in addition to Nokogiri&lt;/span&gt;
&lt;span class="c1"&gt;# Open-uri allows you to open a URI as if it was a file in Ruby&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nokogiri'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'open-uri'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://ruby-doc.org'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#(Document:0x9998 {&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use the &lt;code&gt;#css&lt;/code&gt; method to query the html by elements and classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'h1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;Ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;org&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'p'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;Help&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;documentation&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="no"&gt;Ruby&lt;/span&gt; &lt;span class="n"&gt;programming&lt;/span&gt; &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query class this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://rubyonrails.org'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#(Document:0x1f1bc {&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.heading__headline'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;Nokogiri::XML::Element:0x1fb94 name="div" attributes=[#&amp;lt;Nokogiri::XML...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;headline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;

        &lt;span class="no"&gt;Compress&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;complexity&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;modern&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="no"&gt;Learn&lt;/span&gt; &lt;span class="n"&gt;just&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt; &lt;span class="n"&gt;leveling&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;Ruby&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt; &lt;span class="n"&gt;scales&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="no"&gt;HELLO&lt;/span&gt; &lt;span class="no"&gt;WORLD&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="no"&gt;IPO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="no"&gt;You&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;good&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="no"&gt;Over&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;past&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;decades&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;taken&lt;/span&gt; &lt;span class="n"&gt;countless&lt;/span&gt; &lt;span class="n"&gt;companies&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;millions&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;billions&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="n"&gt;valuations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="no"&gt;Building&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;together&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="no"&gt;Over&lt;/span&gt; &lt;span class="n"&gt;six&lt;/span&gt; &lt;span class="n"&gt;thousand&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;contributed&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;many&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;served&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;community&lt;/span&gt; &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="n"&gt;evangelism&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;bug&lt;/span&gt; &lt;span class="n"&gt;reports&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;Join&lt;/span&gt; &lt;span class="n"&gt;us!&lt;/span&gt;

        &lt;span class="no"&gt;Everything&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="no"&gt;Rails&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="n"&gt;framework&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;It&lt;/span&gt; &lt;span class="n"&gt;ships&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="n"&gt;needed&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;amazing&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;front&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="no"&gt;Optimized&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;happiness&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

        &lt;span class="no"&gt;Let&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great!  Now you have a general idea of how Nokogiri works!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And now for free bonus content...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's search a webpage's content.  For instance, it's basketball season at the time of this writing, so let's see if the homepage to ESPN talks about basketball.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;espn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nokogiri&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://www.espn.com'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#(Document:0x259e0 {&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;# For this we will use a Regular Expression (RegEx)&lt;/span&gt;
&lt;span class="c1"&gt;# The Regular Expression goes between forward slashes&lt;/span&gt;
&lt;span class="c1"&gt;# And the 'i' flag makes the search case-insensitive&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;espn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/basketball/i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it!  And we didn't even have to visit the website to find out that ESPN refers to basketball 32 times on it's homepage! Wow...&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>gem</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
