Sunday, September 28, 2014

More Late Night Ruby Fun

Late Friday/Early Saturday morning, after the wife and kids found solace in sleep, I sat awake in a fevered pitch to patch my laptops and ruby install. I had to install the bash exploit patch, because security!

I also had to take a good stab at compiling the ruby TK library that comes with it.
No luck there though.

I had an adventure when I updated Ruby to Ruby 2.1.3. Basically, I deleted my whole ruby installation and recompiled from source. This left me with no ruby gems. Fortunately, because of my previous late night ruby thinking session, I had a list of gems. It's a slightly dated list, I'd installed the rubyXL gem a couple of night ago, but it is a good start.
I've automated gem installation before, using a simple script to install the gems from a list. I decided to create a couple of stand alone methods and a short script to 1. Create a list of gems currently installed on the system. 2. Install the list of gems (while determining if a gem has already been installed). 3. Determine if any gems in the list I have are missing without installing any new gems.

Objective 1 was easily accomplished. I took my one-liner from the other night and broke it down into a method using a "do... end" block.

I chose to do the method this way because I believe it makes the method more readable. Plus, the rest of the methods in the file are multiline by necessity and it echoes their format.


Objective 2 provided more of a challenge. The original script I wrote installed all the gems listed whether they were already installed or not. Sometimes one gem depends on another for installation, so it gets installed before a gem further up the list. You can still "install" the gem, even if it's already been installed as a dependency, but this adds to the time the script takes to execute. I decided that if I had already installed a gem, whether as a dependency or as part of a previous installation, then I didn't want to reinstall it.


That was a good enough place to stop for the night.
Some cautionary notes:
I'm doing this on Ubuntu 14.04, and you'll see a sudo in there. A unix purist might say that it would be better to su to the superuser and execute without the sudo. I got no problem with that. Understand what you are doing when you use sudo. I execute this script because I wrote it and I know what it says. Don' t do nothin' with sudo you don't understand. That's how things get borked fast.

Also, I don't check for the existence of the gemlist.txt file. I haven't needed that functionality so I haven't created it.

Last night when I got home from work, I watched a little tv while doing laundry,  and then remembered that I'd left my little script here hanging. I still needed a way to check and see if a gem was in the gemlist.txt file.


The hardest part about writing this script was figuring out how to get two arrays created and then subtracting them. For some reason split wasn't behaving as expected. I chalk it up to general tiredness.

At the bottom of this file, I stitched my methods together using an if else ladder.

Everything works!
I know that choice #2 isn't really doing what it says it does. If a gem is already installed on the system, but not in the gemlist file, then it's not on both lists, and it's not installed, nor is it placed in the gemlist file.

Also, I'm sure that there's a better way to do the menu. Perhaps using a hash or something.
One thing this file won't do is install gems that aren't in your install path. Currently I have one gem installed that's built from the gemspec in the gem itself.
One way around this would be to store the gemlist in a csv file or perhaps a spreadsheet, and carry the installation path in there.
Right now though, the file is useful.
I've saved it as a gist on github.

Maybe you can find it useful too!

Sunday, September 21, 2014

"Way to Commit Soldier!"

I'm not a soldier, but that is one of the funnier lines in Madagascar 3.



The pertinent quote begins about 35 seconds in, but this whole scene is what I would call "high comedy".

I do however, want to commit, especially when it comes to committing more code that is. For 13 of the last 14 days, I've made at least one commit to projects I'm working on under Github. I want better programming skills. I believe that the best way to become a better programmer is to read code every day, and write code every day. Sometimes, the code I write isn't very complicated. Saturday I restructured the way I had some test steps written in a code library that will serve as the math problem generation engine for an application I'm developing for my kids. It wasn't very complicated, didn't change the world, but my habits were shaped into a design where such a refactor becomes automatic in the next code library. Other projects I've been working on are an effort to track student reading habits that reports out to a spreadsheet, and a ruby gem that serves as a wrapper for the EBird API.
I'm practicing and learning several different things at once. In my own code libraries, I'm practicing how to develop using the  "Red, Green, Refactor" methodology of cucumber and RSpec. I'm also learning how to write tests that make sense for code libraries that already exist, and I'm learning how to upgrade a library with the latest implementation of that library's methods and objects.
In short, I'm having fun, lots of challenging fun. It's the sort of fun that leads to more and better opportunities for employment and personal development. Committing every day reminds me of what I love about programming, each solution to a program is a unique implementation of patterns, and I love those patterns. It's like the rotunda in Beethoven's works, not the same, but the same is there when he gets around to it. The Bible says in Ecclesiastes chapter 5:

  18 Behold, what I have seen to be good and fitting is to eat and drink and find enjoyment in all the toil with which one toils under the sun the few days of his life that God has given him, for this is his lot.  19 Everyone also to whom God has given wealth and possessions and power to enjoy them, and to accept his lot and rejoice in his toil—this is the gift of God.
 I hope your work helps you find enjoyment. I know what little bit of programming I do at work helps me enjoy my job. I know it encourages me to seek out further skill so I can advance and enjoy it even more. Committing code every day shows me the enjoyment of my toil, and I believe there's nothing better you can do than enjoy whatever it is you are doing.

Saturday, September 6, 2014

Some Quick Late Night Ruby Fun

I should be asleep, but I'm not. Instead I'm up hacking around with ruby, taking some online classes, and generally having a good time.
In an effort to train myself in one discipline, I'm taking some online classes for ruby/ruby on rails/webdevelopment.

The kids and wife have all gone to bed, so I went through a course level about the ActiveSupport library, and started playing around in IRB with what I had learned. Eventually I found myself exercising one of my favorite ruby "koans" : writing a list of the gems I have installed on my computer into a text file. In the past I wrote this as a script that I would execute shortly before system updates or new ruby builds, so I can quickly install the ruby gems I use.

One of the things I've always wanted to do is "get it on one line" of ruby code. I started by executing the following in irb:

`gem list`

The backticks around gem list tell the interpreter "Go to your native environment (bash in this case) and execute the command gem list". The result is  a list of gems, including all the current versions installed, listed like so:

"twitter (5.11.0, 5.10.0, 5.9.0)\ntzinfo (1.2.2, 1.2.1, 1.1.0)\nuglifier (2.5.3, 2.5.1, 2.5.0)\nwatchr (0.7)\nxpath (2.0.0)\nyajl-ruby (1.2.1)\nzip (2.0.2)\n"

That's cool, but I don't necessarily need to know the versions. So the next step was to remove the versions from gems. I needed a regex and gsub to do that.

`gem list`.gsub(/\s[(].*[)]/, "")

this means, "Give me a string where we substitute everything in between two sets of parentheses including the parentheses and the space in front of the opening parenthesis, with an empty string."
That gave me something that looked like:

"twitter\ntzinfo\nuglifier\nwatchr\nxpath\nyajl-ruby\nzip\n"

This gave me a single string of the list of gems installed. I then rediscovered how to open a file and properly write to the file. Several iterations of using File.open do blocks later, I decide to go ahead and use the script below to write the file all in one line:

File.open("gemlist.txt", "w") {|file| file.write `gem list`.gsub(/\s[(].*[)]/, "")}
Now when I use a text editor to view gemlist.txt I see this:

twitter
tzinfo
uglifier
watchr
xpath
yajl-ruby
zip

And more importantly, I can use ruby to parse the file, and reload the gems I need to reinstall next time I build ruby!

The end!