<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.6.2">Jekyll</generator><link href="https://blog.blakeerickson.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.blakeerickson.com/" rel="alternate" type="text/html" /><updated>2022-06-19T13:23:00+00:00</updated><id>https://blog.blakeerickson.com/</id><title type="html">Blake Erickson</title><subtitle>A blog about my programming adventures. I'm quite fond of ruby, rails, ember, api's, json, markdown, linux, vim, puppet, docker/moby, open source, git, discourse, podcasts, and improving my craft.
</subtitle><entry><title type="html">Rake Task with an Arbitrary Amount of Arguments</title><link href="https://blog.blakeerickson.com/rake-task-multiple-arguments" rel="alternate" type="text/html" title="Rake Task with an Arbitrary Amount of Arguments" /><published>2019-07-12T07:00:00+00:00</published><updated>2019-07-12T07:00:00+00:00</updated><id>https://blog.blakeerickson.com/rake-task-multiple-arguments</id><content type="html" xml:base="https://blog.blakeerickson.com/rake-task-multiple-arguments">&lt;p&gt;I’m currently working on a rake task where I need to pass in an arbitrary amount
of values. I couldn’t even remember at first how to even pass in arguments to a
rake task, so let’s cover that first.&lt;/p&gt;

&lt;p&gt;For this example we are going to create a file called &lt;code class=&quot;highlighter-rouge&quot;&gt;raketask.rb&lt;/code&gt; inside of an
empty directory. And inside of that file we can create our first task like so:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;A sample task&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:print_hello&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you save and close the file we can run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake -T&lt;/code&gt; and it will print out a
list of tasks that is knows about:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake print_hello      # A sample task
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we can call this task with the following command:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake print_hello
hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s make another task with an argument:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Say hi&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we run &lt;code class=&quot;highlighter-rouge&quot;&gt;rake -T&lt;/code&gt; again:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake print_hello      # A sample task
rake say_hello[name]  # Say hi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlike command line bash scripts or even calling a ruby script with multiple
args you can’t just separate them by spaces in a rake task like this:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ruby my-sample-script.rb arg1 arg2 arg3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rake task arguments go inside brackets:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake say_hello[blake]
Hello blake
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now how do we specify multiple arguments? By specifying each one inside of the
task declaration:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Two args&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:two_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you can run it by specifying args in a comma separated list (with no
spaces!):&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake two_args[blake,erickson]
Hello blake erickson
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now onto the tricky part that I’m still not 100% satisfied with, is how do you
pass in an arbitrary amount of arguments to a rake task? For my case I need to
pass in a list of values, but I’m not sure how many there will be.&lt;/p&gt;

&lt;p&gt;To do this you will not specify the args like we did before inside of the task
declaration. The problem with this is now it won’t show the args when running
&lt;code class=&quot;highlighter-rouge&quot;&gt;rake -T&lt;/code&gt;. So to handle an arbitrary amount of args you can use the
&lt;a href=&quot;https://stackoverflow.com/a/28654953/588458&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;args.extras&lt;/code&gt;&lt;/a&gt; method like so:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Arbitrary args, pass in a comma separated list&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:arbitrary_args&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;There are &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extras&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; args&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extras&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can run the arbitrary args command with:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake arbitrary_args[banana,apple,orange,mango]
There are 4 args
banana
apple
orange
mango
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’m not totally satisfied with specifying an arbitrary amount of
arguments this way, but it does get the job done. Hopefully this helps you in
your &lt;a href=&quot;https://martinfowler.com/articles/rake.html&quot;&gt;rake&lt;/a&gt; task adventures.&lt;/p&gt;</content><author><name></name></author><summary type="html">I’m currently working on a rake task where I need to pass in an arbitrary amount of values. I couldn’t even remember at first how to even pass in arguments to a rake task, so let’s cover that first.</summary></entry><entry><title type="html">Using Ruby to Save Cookies</title><link href="https://blog.blakeerickson.com/using-ruby-to-save-cookies" rel="alternate" type="text/html" title="Using Ruby to Save Cookies" /><published>2019-07-11T07:00:00+00:00</published><updated>2019-07-11T07:00:00+00:00</updated><id>https://blog.blakeerickson.com/using-ruby-to-save-cookies</id><content type="html" xml:base="https://blog.blakeerickson.com/using-ruby-to-save-cookies">&lt;p&gt;Like I mentioned in my &lt;a href=&quot;https://blog.blakeerickson.com/using-curl-to-save-cookies&quot;&gt;previous post&lt;/a&gt; about saving cookies with cURL in this
post I’m going to show you how to do it with ruby.&lt;/p&gt;

&lt;p&gt;I found &lt;a href=&quot;https://stackoverflow.com/a/32868560/588458&quot;&gt;this stackoverflow answer&lt;/a&gt; that talks about using &lt;a href=&quot;https://github.com/sparklemotion/http-cookie&quot;&gt;http-cookie&lt;/a&gt;
which doesn’t look like it has been updated in over 3 years, but it did work
just fine.&lt;/p&gt;

&lt;p&gt;I created the &lt;a href=&quot;https://github.com/oblakeerickson/golds_checkin&quot;&gt;golds_checkin&lt;/a&gt; repo to store the ruby code of this project.
Currently it is just an app.rb file, but I will most likely turn it into an
actual ruby gem.&lt;/p&gt;

&lt;p&gt;Here is the output of my app.rb file:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'yaml'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'net/http'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http-cookie'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'cgi'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GoldsCheckin&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;YAML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'config.yml'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@jar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CookieJar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;login&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'https://mico.myiclubonline.com/iclub/j_spring_security_check'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;use_ssl: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;form_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;j_username&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'username'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;j_password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Set-Cookie'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;vi&quot;&gt;@jar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fetch_checkins&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;low_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CGI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%m/%d/%Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;high_date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CGI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%m/%d/%Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://mico.myiclubonline.com/iclub/account/checkInHistory.htm?lowDate=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;low_date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;amp;highDate=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;high_date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;use_ssl: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Cookie'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cookie_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@jar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;golds_checkin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GoldsCheckin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;golds_checkin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;login&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;golds_checkin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch_checkins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Basically there are two methods, ‘login’ and ‘fetch_checkins’. ‘login’ reads my
credentials out of a yaml file and makes a POST request wich then sets the
returned cookies into the @jar instance variable so that we can use it for
subsequent requests. Once we are logged in then we can call ‘fetch_checkins’
which I have set to only fetch today’s date. This call reads from the cookie jar
in order to make an authenticated request.&lt;/p&gt;

&lt;p&gt;From these two posts (this one and &lt;a href=&quot;https://blog.blakeerickson.com/using-curl-to-save-cookies&quot;&gt;yesterdays&lt;/a&gt;) you can start to see my
process for making an app. I usually start with just playing around on the
command line. Then I translate all of that knowledge into a simple app.rb file.
From there I think it kind of depends what my end goal is, but then the app.rb
file evolves in some way where it no longer just lives on my local computer, but
gets turned into a ruby gem to be used in another project, or it evovles into a
larger web application.&lt;/p&gt;</content><author><name></name></author><summary type="html">Like I mentioned in my previous post about saving cookies with cURL in this post I’m going to show you how to do it with ruby.</summary></entry><entry><title type="html">Using cURL to Save Cookies</title><link href="https://blog.blakeerickson.com/using-curl-to-save-cookies" rel="alternate" type="text/html" title="Using cURL to Save Cookies" /><published>2019-07-10T07:00:00+00:00</published><updated>2019-07-10T07:00:00+00:00</updated><id>https://blog.blakeerickson.com/using-curl-to-save-cookies</id><content type="html" xml:base="https://blog.blakeerickson.com/using-curl-to-save-cookies">&lt;p&gt;Just for fun I want to automatically track if I go to the gym or not. Every time
I go to Golds Gym I have to scan my card that I keep on my key chain so there is
an electronic record of me going to the gym or not. I did not know about this
when I signed up, but Golds Gym does have a &lt;a href=&quot;https://mico.myiclubonline.com/iclub/members/signin.htm&quot;&gt;crappy website&lt;/a&gt; for managing your
membership and on there you can see a record of every time you have checked into
the gym.&lt;/p&gt;

&lt;p&gt;The problem I have with this website is that they don’t have an API and it
mostly requires javascript to use it. This makes automatically fetching the data
I need very tricky. Using Firefox’s developer tools you can inspect the http
requests and copy them as cURL so that you can kind of reverse engineer how to
authenticate and fetch data.&lt;/p&gt;

&lt;p&gt;This works pretty well and I was able to get everything I needed from the
command line using cURL commands, but unfortunatley it only worked for the
lifetime of the session cookie. Even though I have worked with web technology
for many years I actually haven’t done a whole lot with cookies. The copy as
cURL command from Firefox will actually copy over all of the cookies into the
cURL request, but that wasn’t exactly what I was after. Through some digging
around I found a &lt;a href=&quot;https://ec.haxx.se/http-cookies.html&quot;&gt;great resource on cURL&lt;/a&gt; that mentions how to save and
retreive cookies from a text file.&lt;/p&gt;

&lt;p&gt;To save a cookie you can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;-c&lt;/code&gt; flag followed by the name of the cookie
file you want to save. Here is an example:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -c cookie.txt https://example.com?creds=asdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you then want to use those cookies you can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;-b&lt;/code&gt; flag like this:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -b cookie.txt https://example.com/data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So now I can run one cURL command to authenticate with my username and password
which will save a session token in my cookie file. And then I can run another
cURL command using the cookie file to fetch the data I’m after. Pretty cool.&lt;/p&gt;

&lt;p&gt;Now my next steps are to do this all in ruby. After that I’m hoping I can add
this to my private Discourse instance somehow so that I can be awarded a custom
gym badge every day I go or for going so many days in a row.&lt;/p&gt;</content><author><name></name></author><summary type="html">Just for fun I want to automatically track if I go to the gym or not. Every time I go to Golds Gym I have to scan my card that I keep on my key chain so there is an electronic record of me going to the gym or not. I did not know about this when I signed up, but Golds Gym does have a crappy website for managing your membership and on there you can see a record of every time you have checked into the gym.</summary></entry><entry><title type="html">Bug Crushing Adventure</title><link href="https://blog.blakeerickson.com/bug-crushing-adventure" rel="alternate" type="text/html" title="Bug Crushing Adventure" /><published>2018-10-31T07:00:00+00:00</published><updated>2018-10-31T07:00:00+00:00</updated><id>https://blog.blakeerickson.com/bug-crushing-adventure</id><content type="html" xml:base="https://blog.blakeerickson.com/bug-crushing-adventure">&lt;p&gt;At &lt;a href=&quot;https://discourse.org&quot;&gt;Discourse&lt;/a&gt; we have a new “game” that we play where we have a running bug
crushing topic on our internal team Discourse site that is always assigned to
someone. If this topic is assigned to you then you need to look through the
application logs of all the sites that we host to find a bug and then fix it.
Once the bug is fixed, post a reply to the topic with the details and then
assign the topic to a new person. So far it has been working great and it has
given me, a developer who is often busy working on infrastructure related ops
work, an opportunity to commit more code changes to the core Discourse app. Also
this helps spread the bug fixing responsibility across many more team members so
it doesn’t just end up being a couple people fixing all the bugs.&lt;/p&gt;

&lt;p&gt;Yesterday was my turn. I actually found a bug that I noticed was
happening on a couple of sites. I then spent a large chunk of my day trying to
fix it and replicate it locally. The initial hard part was getting the plugin
installed locally with the right environment variables. Once I was able to debug
the code locally something just didn’t add up. LIke this literally could not be
happening. After much frustration and even pairing with my awesome coworker we
figured out that this bug was actually &lt;a href=&quot;https://github.com/discourse/discourse-backup-uploads-to-s3/commit/652267988416f2d922c595cab50a2b9823bacf51&quot;&gt;fixed 27 days ago&lt;/a&gt;. So we then
checked the deploy history for those sites and sure enough those sites just
hadn’t been deployed since then and didn’t have the fix.&lt;/p&gt;

&lt;p&gt;I guess the lesson to learn here is to check git blame to see the last time a
file I’m working on was last modified. Maybe I’ll look into something like
&lt;a href=&quot;https://github.com/tpope/vim-fugitive&quot;&gt;vim-fugitive&lt;/a&gt; so that it is easier for me to see the git blame
history without leaving my trusty editor.&lt;/p&gt;

&lt;p&gt;The good thing about all of this is that I actually learned quite a bit about
the code base by “investing” all of this time trying to fix that bug.&lt;/p&gt;

&lt;p&gt;Luckily I was able to find another bug (which I originally was going to talk
more about in this post) that was showing up in the logs and
&lt;a href=&quot;https://github.com/discourse/discourse/commit/589e3fcaa0c8fed0f6de6e61912c8cc577975ee0&quot;&gt;crush it&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html">At Discourse we have a new “game” that we play where we have a running bug crushing topic on our internal team Discourse site that is always assigned to someone. If this topic is assigned to you then you need to look through the application logs of all the sites that we host to find a bug and then fix it. Once the bug is fixed, post a reply to the topic with the details and then assign the topic to a new person. So far it has been working great and it has given me, a developer who is often busy working on infrastructure related ops work, an opportunity to commit more code changes to the core Discourse app. Also this helps spread the bug fixing responsibility across many more team members so it doesn’t just end up being a couple people fixing all the bugs.</summary></entry><entry><title type="html">Rails Collection Routes</title><link href="https://blog.blakeerickson.com/rails-collection-routes" rel="alternate" type="text/html" title="Rails Collection Routes" /><published>2018-10-28T07:00:00+00:00</published><updated>2018-10-28T07:00:00+00:00</updated><id>https://blog.blakeerickson.com/rails-collection-routes</id><content type="html" xml:base="https://blog.blakeerickson.com/rails-collection-routes">&lt;p&gt;While working on Pistachio, the todo app I’m building to practice rails, I
wanted to work on a new feature that would allow me to order lists. I already
had the ability to order items in a list but not the lists themselves. As I was
working on this feature I realized that maybe my original route for sorting
items wasn’t actually the best route to be using especially since it would mean
that I would have two &lt;code class=&quot;highlighter-rouge&quot;&gt;sort&lt;/code&gt; routes on my lists controller.&lt;/p&gt;

&lt;p&gt;Here is what I originally had for sorting list items in my &lt;code class=&quot;highlighter-rouge&quot;&gt;config/routes.rb&lt;/code&gt;
file:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;resources :lists, only: [:index, :show, :new, :create, :destroy, :edit, :update] do
  patch :sort
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which means the route looks like this &lt;code class=&quot;highlighter-rouge&quot;&gt;lists/:list_id/sort&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This actually worked fine, but it was a bit weird that I had my sort item logic
inside of my lists controller. I’m sure I original did it this way because I
wasn’t sure how to make a collection route that would hit my items controller
without requiring an item id, nor did I know it was called a collection route
that I was looking for.&lt;/p&gt;

&lt;p&gt;Before we fix the lists route let’s go ahead and create this collection based sort
route under the items resource:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;resources :items, only: [:create, :destroy, :edit, :update] do
  patch :complete
  collection do
    patch :sort
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create a route for us that looks like &lt;code class=&quot;highlighter-rouge&quot;&gt;/lists/:list_id/items/sort&lt;/code&gt;. Which then means I can move the contents of the current sort method in my lists controller to the sort method of my items controller where it should have been in the first place.&lt;/p&gt;

&lt;p&gt;And now we can move the current &lt;code class=&quot;highlighter-rouge&quot;&gt;patch :sort&lt;/code&gt; route that is part of the lists resources into a collection so that we can use it for sorting lists. It should now look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;resources :lists, only: [:index, :show, :new, :create, :destroy, :edit, :update] do
  patch :sort
  collection do
    patch :sort
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will give us a route of ‘/lists/sort` which is exactly what we want so that the sort route isn’t tied to any specific route id, but instead to the whole collection of lists.&lt;/p&gt;</content><author><name></name></author><summary type="html">While working on Pistachio, the todo app I’m building to practice rails, I wanted to work on a new feature that would allow me to order lists. I already had the ability to order items in a list but not the lists themselves. As I was working on this feature I realized that maybe my original route for sorting items wasn’t actually the best route to be using especially since it would mean that I would have two sort routes on my lists controller.</summary></entry><entry><title type="html">Finally Turning AudioGrab Into a Rails App</title><link href="https://blog.blakeerickson.com/finally-turning-audiograb-into-a-rails-app" rel="alternate" type="text/html" title="Finally Turning AudioGrab Into a Rails App" /><published>2018-08-26T06:00:00+00:00</published><updated>2018-08-26T06:00:00+00:00</updated><id>https://blog.blakeerickson.com/finally-turning-audiograb-into-a-rails-app</id><content type="html" xml:base="https://blog.blakeerickson.com/finally-turning-audiograb-into-a-rails-app">&lt;h4 id=&quot;645-pm&quot;&gt;6:45 PM&lt;/h4&gt;

&lt;p&gt;Okay today I’m finally going to make a Rails app for AudioGrab. I think creating
a cli app was a great first step, but having a rails app that I could have a
bookmarklet talk to is what I really want. The &lt;a href=&quot;https://github.com/oblakeerickson/audiograb&quot;&gt;original audiograb&lt;/a&gt; I made
back in 2013. My current &lt;a href=&quot;https://github.com/oblakeerickson/audio_grab&quot;&gt;cli version&lt;/a&gt; I just opened sourced.&lt;/p&gt;

&lt;p&gt;My goal for tonight is to make the most basic rails app and get it deployed to
production. All I want it to do is have an input box for the youtube url with a
submit button. It then will take that url and download the youtube video,
convert it to mp3, and then upload it to my overcast account.&lt;/p&gt;

&lt;p&gt;This means that I won’t have user accounts yet, but maybe I can just protect it
with basic auth or something.&lt;/p&gt;

&lt;h4 id=&quot;708-pm&quot;&gt;7:08 PM&lt;/h4&gt;

&lt;p&gt;Okay I just ran &lt;code class=&quot;highlighter-rouge&quot;&gt;rails new audio_grab_app&lt;/code&gt; to generate my new app, ran &lt;code class=&quot;highlighter-rouge&quot;&gt;rails
server&lt;/code&gt; to verify that it runs, and now I’m going to push it up to github.&lt;/p&gt;

&lt;p&gt;Okay I created my public repo on github and added a license.&lt;/p&gt;

&lt;p&gt;Then I ran &lt;code class=&quot;highlighter-rouge&quot;&gt;git remote add origin &amp;lt;repo-name&amp;gt;&lt;/code&gt;. Followed by &lt;code class=&quot;highlighter-rouge&quot;&gt;git pull --rebase
origin master&lt;/code&gt; to pull down my license. Then I &lt;a href=&quot;https://github.com/oblakeerickson/audio_grab_app/commit/a2800d55de4a144266fa7ca98d00e547527bb9b0&quot;&gt;committed&lt;/a&gt; and pushed my current
changes.&lt;/p&gt;

&lt;p&gt;Okay now its dinner time.&lt;/p&gt;

&lt;h4 id=&quot;917-pm&quot;&gt;9:17 PM&lt;/h4&gt;

&lt;p&gt;Now that I’m back from dinner and playing bed wars with my 9 year old, let’s see
if we can write some rails code.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/rails generate controller Links create&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Oops I probably should create the new action for my form and make that the first
page you go to. Create will handle the form submission.&lt;/p&gt;

&lt;p&gt;Okay I just created new.html.erb and changed the route in routes.rb to `get
‘links/new’.&lt;/p&gt;

&lt;p&gt;Now I need to make my form. I’m not going to persist anything to the database
yet for this because I don’t want to remember any of these links. So I’m going
to create a new Link model, but not have it inherit from active record.&lt;/p&gt;

&lt;p&gt;So my model class is called Link and I was also going to call my value I’m
storing called link as well, but I think that will get confusing so I’m going to
just call it url.&lt;/p&gt;

&lt;p&gt;Okay my form is working and I’m able to submit it. Now I need to hook up all the
stuff in my command line app after the form is submitted, but first I’m going to
&lt;a href=&quot;https://github.com/oblakeerickson/audio_grab_app/commit/14b17f804f68732bd9544c358766508e8abf68e7&quot;&gt;commit&lt;/a&gt; what I have so far.&lt;/p&gt;

&lt;h4 id=&quot;1102-pm&quot;&gt;11:02 PM&lt;/h4&gt;

&lt;p&gt;Just got back from a walk. I think the first thing I need to do is be able to
load some secrets for overcast. For obvious reasons I don’t want them to be
checked into source control, but I need my controller or rake task to be able to
read from them.&lt;/p&gt;

&lt;p&gt;Ohh maybe I can use the new credentials feature:&lt;/p&gt;

&lt;p&gt;https://medium.com/@wintermeyer/goodbye-secrets-welcome-credentials-f4709d9f4698&lt;/p&gt;

&lt;p&gt;Maybe I should also watch (or listen) this YouTube video on the subject:&lt;/p&gt;

&lt;p&gt;https://www.youtube.com/watch?v=fS92ZDfLhng&lt;/p&gt;

&lt;p&gt;Okay, cool I got credentails working. What I want to happen is create a
background process to download and the YouTube video so that the web page
doesn’t stay open forever if I had it do all the work in the controller. I don’t
really want sidekiq right now, so I think I can just do this in a rake task or
something. Maybe I could use &lt;a href=&quot;https://edgeguides.rubyonrails.org/active_job_basics.html&quot;&gt;Active Job&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Sweet I just created my active job called ProcessVideo and pretty much just
copied what I had in this &lt;a href=&quot;https://github.com/oblakeerickson/audio_grab/commit/cbf6f344ce606b73f2d2c615bc803382216b3110&quot;&gt;initial commit&lt;/a&gt; from audio_grab.&lt;/p&gt;

&lt;p&gt;youtube-dl ran just fine and created a .mp3 file at the application root. I
wonder if I should store it in the &lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp&lt;/code&gt; directory? I then ran into an error I
think trying to load the file. Ohh I see what I did. The variable was still
called files instead of just file. I also just changed it to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp&lt;/code&gt;
directory instead. Let’s see if it runs this time.&lt;/p&gt;

&lt;p&gt;Wow it actually worked. My form returned right away while it processed the video
in the background and then uploaded it to overcast.&lt;/p&gt;

&lt;p&gt;There are still some improvements like making sure I don’t just grab the first
.mp3 file from the tmp directory but the actual video that was downloaded incase
I’m in the middle of processing multiple videos.&lt;/p&gt;

&lt;p&gt;Also I still need to deploy it, but I’ll have to do that another day. Here is my
&lt;a href=&quot;https://github.com/oblakeerickson/audio_grab_app/commit/06cfa9052277725a94614e4b2310e5fc0102380c&quot;&gt;last commit&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html">6:45 PM</summary></entry><entry><title type="html">How to Clone Git Repositores with Puppet on OS X</title><link href="https://blog.blakeerickson.com/how-to-clone-git-repositories-with-puppet-on-osx" rel="alternate" type="text/html" title="How to Clone Git Repositores with Puppet on OS X" /><published>2018-08-26T06:00:00+00:00</published><updated>2018-08-26T06:00:00+00:00</updated><id>https://blog.blakeerickson.com/how-to-clone-git-repositories-with-puppet-on-osx</id><content type="html" xml:base="https://blog.blakeerickson.com/how-to-clone-git-repositories-with-puppet-on-osx">&lt;p&gt;I’m currently in the process of puppetizing my macOS based laptop, but I’m
noticing some external modules like &lt;a href=&quot;https://blog.blakeerickson.com/how-to-clone-git-repositories-with-puppet&quot;&gt;vcsrepo&lt;/a&gt; don’t have OS X support.&lt;/p&gt;

&lt;p&gt;To clone git repositories using puppet on OS X I’m doing:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;exec { 'git clone git@github.com:org/repo.git /full-path/repo':
  path    =&amp;gt; '/usr/local/bin',
  user    =&amp;gt; 'blake'
  creates =&amp;gt; '/full-path/repo'
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which seems to be getting the job done.&lt;/p&gt;</content><author><name></name></author><summary type="html">I’m currently in the process of puppetizing my macOS based laptop, but I’m noticing some external modules like vcsrepo don’t have OS X support.</summary></entry><entry><title type="html">Installing Puppet on OS X</title><link href="https://blog.blakeerickson.com/installing-puppet-on-osx" rel="alternate" type="text/html" title="Installing Puppet on OS X" /><published>2018-08-25T06:00:00+00:00</published><updated>2018-08-25T06:00:00+00:00</updated><id>https://blog.blakeerickson.com/installing-puppet-on-osx</id><content type="html" xml:base="https://blog.blakeerickson.com/installing-puppet-on-osx">&lt;p&gt;My main computer right now is a Linux based desktop computer, but my laptop is a
13” MacBook Pro running the latest version of OS X. Because I use my desktop the
most I feel like whenever I do need to be portable and grab my laptop, it is
always out of sync with my desktop. Then rather than being productive and
getting done what I need to get done I spend my time configuring my laptop.&lt;/p&gt;

&lt;p&gt;I’ve been trying to be really good with my current desktop and configure
everything via puppet, my goal is that I can also puppettize my OS X based
laptop, so I set out to do just that today. I didn’t realize that full support
for Puppet and external modules really is only on Linux distros, but they do
have an official OS X installer, so this is looking promising.&lt;/p&gt;

&lt;p&gt;To install Puppet on OS X visit the offical &lt;a href=&quot;https://puppet.com/docs/puppet/5.3/install_osx.html&quot;&gt;Installing Puppet agent: MacOS&lt;/a&gt;
page. And on step #2 click the package link that takes you to &lt;a href=&quot;https://downloads.puppetlabs.com/mac/&quot;&gt;this
download&lt;/a&gt; page. Actully just visit this &lt;a href=&quot;https://downloads.puppetlabs.com/mac/puppet/10.13/x86_64/&quot;&gt;/mac/puppet/10.13/x86_64&lt;/a&gt; page
and download &lt;a href=&quot;https://downloads.puppetlabs.com/mac/puppet/10.13/x86_64/puppet-agent-latest.dmg&quot;&gt;puppet-agent-latest.dmg&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This will download the puppet agent installer. Click on it and follow the
install instructions. I’m actually running a masterless puppet install so I
don’t actually need the puppet agent running. Once puppet is installing you can
then turn off the puppet agent with this command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo puppet resource service pxp-agent ensure=stopped enable=false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also verify that puppet is installed by running:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;puppet --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can browse to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/puppetlabs&lt;/code&gt; and edit your puppet config.&lt;/p&gt;</content><author><name></name></author><summary type="html">My main computer right now is a Linux based desktop computer, but my laptop is a 13” MacBook Pro running the latest version of OS X. Because I use my desktop the most I feel like whenever I do need to be portable and grab my laptop, it is always out of sync with my desktop. Then rather than being productive and getting done what I need to get done I spend my time configuring my laptop.</summary></entry><entry><title type="html">Azure Table Storage</title><link href="https://blog.blakeerickson.com/azure-table-storage" rel="alternate" type="text/html" title="Azure Table Storage" /><published>2018-08-24T06:00:00+00:00</published><updated>2018-08-24T06:00:00+00:00</updated><id>https://blog.blakeerickson.com/azure-table-storage</id><content type="html" xml:base="https://blog.blakeerickson.com/azure-table-storage">&lt;p&gt;One of the things that I like about Azure Table Storage is that it is cheap and
it can be quite fast too if you know the partition key and row key of the thing
you are searching for.&lt;/p&gt;

&lt;p&gt;You can actually store several gigs of data for just a few cents every single
month.&lt;/p&gt;

&lt;p&gt;One use for table storage could be application log data. Or perhaps there is
some database table in your sql database that is trastically larger than any
other table in your db that you could extract out and store that data in azure
table storage instead?&lt;/p&gt;

&lt;p&gt;Here is some key information about Azure Table Storage&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key-Value based&lt;/li&gt;
  &lt;li&gt;Can have 255 properties&lt;/li&gt;
  &lt;li&gt;Each entity size can be up to 1mb&lt;/li&gt;
  &lt;li&gt;Data is stored by partition key and row key
    &lt;ul&gt;
      &lt;li&gt;Improve scalability by limiting number of partitions&lt;/li&gt;
      &lt;li&gt;Batch operations can be affected by having a lot of partitions&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Supposedly you are only charged the amount of data you are storing, but on the
pricing page it says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We charge $0.00036 per 10,000 transactions for tables. Any type of operation
against the storage is counted as a transaction, including reads, writes, and
deletes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So on the Azure 70-532 exam you might need to be careful how you answer a
question about this.&lt;/p&gt;

&lt;p&gt;One of the things that I don’t always like about using cloud only resources like
Azure Table Storage is that you can’t really run them locally on your dev
machine. There is however a &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/storage/common/storage-use-emulator&quot;&gt;storage emulater&lt;/a&gt; you can run locally on Windows and there is
also a non-Microsoft &lt;a href=&quot;https://github.com/azure/azurite&quot;&gt;open source version&lt;/a&gt; you can run on Linux, OS X, and Windows.&lt;/p&gt;

&lt;p&gt;Another tool to checkout is the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/vs-azure-tools-storage-manage-with-storage-explorer?tabs=linux&quot;&gt;Storage Explorer&lt;/a&gt; which you can use instead
of the Azure portal to view/edit data in your Table Storage account.&lt;/p&gt;</content><author><name></name></author><summary type="html">One of the things that I like about Azure Table Storage is that it is cheap and it can be quite fast too if you know the partition key and row key of the thing you are searching for.</summary></entry><entry><title type="html">Getting started with Azure Cosmos DB</title><link href="https://blog.blakeerickson.com/cosmos-db" rel="alternate" type="text/html" title="Getting started with Azure Cosmos DB" /><published>2018-08-23T06:00:00+00:00</published><updated>2018-08-23T06:00:00+00:00</updated><id>https://blog.blakeerickson.com/cosmos-db</id><content type="html" xml:base="https://blog.blakeerickson.com/cosmos-db">&lt;p&gt;In this post I’m going to walk you through how to use the Azure portal to create
a new Cosmos DB and then how to create a database, a collection, a document, and
then query for the document, all from the portal.&lt;/p&gt;

&lt;h3 id=&quot;1-create-a-new-cosmos-db&quot;&gt;(1) Create a new Cosmos DB&lt;/h3&gt;

&lt;p&gt;In the azure portal, click on “Create a resource” and start searching for
“Cosmos DB”. Once it shows up in the search results, possibly as “Azure Cosmos
DB” click on it and you should see this “New Account” blade:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/new-cosmos-db.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You will then need to create a globally unique id for your Cosmos DB. Because
this is just a demo db that I’m going to throw away I just created a 31
character random string “45c6c5768a11937faa708eb2fb0587e” for my db id.&lt;/p&gt;

&lt;p&gt;Next you will need to choose which Cosmos DB API type you would like to use.
Here are the options you can choose from:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/cosmos-db-api-type.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For this example we are going to pick “SQL” which is the “DocumentDB” type.&lt;/p&gt;

&lt;p&gt;Now go ahead and choose the resource group you want to use or create a new one.
For this example let’s just create a new resource group called: “blog-20180823”.&lt;/p&gt;

&lt;p&gt;Now choose the location for you Document DB. I’m going to choose “Central US”.&lt;/p&gt;

&lt;p&gt;I’m also going to turn off geo-redundancy and not turn on Multi Master. I’m also
not going to configure a virtual network.&lt;/p&gt;

&lt;p&gt;Now you can click “Create”.&lt;/p&gt;

&lt;h3 id=&quot;2-create-a-database&quot;&gt;(2) Create a database&lt;/h3&gt;

&lt;p&gt;Once our cosmos db instance has been created click on it in the azure portal and
then select “Data Explorer”. Your screen should now look something like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/cosmos-db-data-explorer.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From this screen select “New Database”. A new blade will open up. Give it a
“Database id” and then click on “OK”.&lt;/p&gt;

&lt;h3 id=&quot;3-create-a-collection&quot;&gt;(3) Create a collection&lt;/h3&gt;

&lt;p&gt;Now that we hava database, which is really just a holder for multiple
collections, we can create our collection by hovering over our database,
selecting the “…” and selecting “New Collection”. The following new collection
blade will appear:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/cosmos-db-add-collection.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s call the Coolection Id “Items”. Set the Storage capacity to “Fixed (10
GB)”. And set the throughput to “400” RU/s. This will make our bill come out to
around $23.10 per month.&lt;/p&gt;

&lt;h3 id=&quot;4-create-a-document&quot;&gt;(4) Create a document&lt;/h3&gt;

&lt;p&gt;Now that we have a collection let’s add a document to it. Normally you would
probably do this through code, bet we can also do this in the portal. Click on
“New Document” and add the following json:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    &quot;id&quot;: &quot;1&quot;,
    &quot;name&quot;: &quot;Buy milk&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then press “Save”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/cosmos-db-item.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;5-create-a-query&quot;&gt;(5) Create a query&lt;/h3&gt;

&lt;p&gt;I know we only have one document in our collection, but we can still query for
it. Click on the Items collection then click on “New SQL Query” and enter in the
following SQL:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SELECT *
FROM items i
WHERE i.id = &quot;1&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://blakestagram.blob.core.windows.net/blog/cosmos-db-query.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Press “Execute Query” and it should return our item.&lt;/p&gt;</content><author><name></name></author><summary type="html">In this post I’m going to walk you through how to use the Azure portal to create a new Cosmos DB and then how to create a database, a collection, a document, and then query for the document, all from the portal.</summary></entry></feed>