Choosing a Ruby gem

Instead of writing yet another list of gems you should be using, i'll try to explain how i choose a gem for a particular task or function. This is by no means a complete checklist, it's just my typical way of going about things.

Rubygems

If you're a Ruby developer you are probably familiar with the website rubygems.org. It's "the" repository for all information about Ruby gems.

Things i find important when looking for a gem:

Number of total downloads

Though it will not tell you whether a gem is any good, it does tell you whether a lot of people looked at it as a good candidate for the job you need done. It's also an indicator for the community you can expect around this gem (helps when looking for tutorials, documentation, and general help).

Release date of the last versions

This will show you how frequently is the gem updated, which is useful to know how fast are fixes and new features introduced.

Sometimes it can happen that a really good gem hasn't had a release in a while. For example a couple of weeks ago i was looking for a gem that wrapped the Marvel Comics API. If you look for gems for that you find that most are really old. Doesn't mean they don't work properly, it just means that the API hasn't changed since and they are still relevant. When that's the case, i usually go for the one that was released last, just because the author had the gift of hindsight over the other ones and might have done a better, more polished job at it. Not always true, but... :)

Dependencies and License

To a lesser degree, i also take a look at these.

The less dependencies a gem has the lighter your code will be. Again, not always true, but it's a good rule of thumb. Also pay attention if the license is compatible with your own project.

    If a particular gem feels like a good candidate, I then visit its...

    ...Github/Repository/Website

    There, i usually check for a couple of things:

    Documentation

    This is how you learn how to use the gem, so it helps if the docs are really good (and maintained!).

    If it's an opensource project (which most gems are), then i also look for:

    Last commit date

    A clear indicator of the health of the gem. Also, take into consideration what i wrote earlier about gems that don't update often: it might be because they just don't need to.

    Number of contributors, commenters, discussions

    They show how active the community is around this gem. If big, it helps later when trying to find information how to do things if you get stuck, for example.

    Number of open issues (and resolved)

    If you take a glance at the last issues, when they were created, when they were replied to or resolved, this will also give you a good idea of how active the developers are, and how fast can you expect a response if you report something.

    Code

    Looking at the source code, though not as important as the rest, can also provide some insight to how performant, optimized the gem is at the job it does. It might also help you figure out if will be easy to monkey patch something to fit your needs later. And who knows, you mighty also learn something new from it :)

    Conclusion

    Though not (by any means) a complete guide for choosing a gem, this might be a good starting point. Also, some of these "metrics" might apply for choosing other software and code libraries.

    Like most things in life, your mileage may vary.

    Happy coding!

    Java in Firefox after v52.0 (Checkpoint VPN)

    Firefox has changed a few things in its plugin infrastructure and that means Java will no longer work properly after version 52.0 (especially if you are using Checkpoint VPN to access work).

    Fortunately one can always install older versions, present here:

    https://ftp.mozilla.org/pub/firefox/releases

    Also, be sure to disable automatic updates in the settings to prevent the browser from updating itself (default).


    Bonus step (if you are on the mac configuring Checkpoint):

    The newest OSX has a safety feature called SIP (System Integration Protection) that will prevent the checkpoint from installing the required files in the system. To work around this, you need to disable it temporarily:

    • Boot into recovery mode (restart and press Command + R on hearing the beep)
    • Open the terminal and type:
    • csrutil disable
    • Reboot
    • Access the vpn and the snx_extender installation step will work.
    • Go back into recovery and enable SIP again:
    • csrutil enable

    Happy VPN'ing

    OCR using the new open Google Cloud Vision API

    Just create a new api key in the developer console, replace it in the code below and it should work. Then you can call "whatever_you_call_the_file.rb /Downloads/some_image_with_text.jpg" and google will OCR-it and the script will print out the recognized text.
    require "base64"
    require 'net/http'
    require 'json'
    
    # Base 64 the input image
    b64_data = Base64.encode64(File.open(ARGV[0], "rb").read)
    
    # Stuff we need
    api_key = "<YOUR_GOOGLE_API_KEY>"
    content_type = "Content-Type: application/json"
    url = "https://vision.googleapis.com/v1/images:annotate?key=#{api_key}"
    data = {
      "requests": [
        {
          "image": {
            "content": b64_data
          },
          "features": [
            {
              "type": "TEXT_DETECTION",
              "maxResults": 1
            }
          ]
        }
      ]
    }.to_json
    
    # Make the request
    url = URI(url)
    req = Net::HTTP::Post.new(url, initheader = {'Content-Type' =>'application/json'})
    req.body = data
    res = Net::HTTP.new(url.host, url.port)
    res.use_ssl = true
    
    # res.set_debug_output $stderr
    
    detected_text = ""
    res.start do |http| 
      puts "Querying Google for image: #{ARGV[0]}"
      resp = http.request(req)
      # puts resp
      json = JSON.parse(resp.body)
      # puts json
      if json && json["responses"] && json["responses"][0]["textAnnotations"] && json["responses"][0]["textAnnotations"][0]["description"]
        detected_text = json["responses"][0]["textAnnotations"][0]["description"]
      end
    end
    
    puts "Google says the image is: #{detected_text}"

    Lock and unlock Ubuntu using your iPhone

    If, like me, you suffer from lazius extremis (lazy bastard, for the layman), you probably hate having to lock your computer when you leave and entering a password when you come back.

    Fear not, young padawan, UDEV and xdotool to the rescue!

    Here's how it works: UDEV (a linux mechanism that detects device events (including USB)) can be configured with rules that fire whenever something changes (i.e. a device is connected or disconnect from the system). When that happens, you want to run a script to lock or unlock your system, based on the type of rule that was fired. So, let's get started:

    1. Create the UDEV rules:
    1.1. Create a new file at /etc/udev/rules.d/100-lock-unlock-with-iphone.rules, with the following contents:

    SUBSYSTEM=="usb", ENV{PRODUCT}=="2bc/12c8/520", ENV{DEVTYPE}=="usb_device", ACTION=="add",    RUN+="/home/youruser/bin/unlock"
    SUBSYSTEM=="usb", ENV{PRODUCT}=="2bc/12c8/520", ENV{DEVTYPE}=="usb_device", ACTION=="remove", RUN+="/home/youruser/bin/lock"

    1.2. In those lines, replace 2bc/12c8/520 with your device product id, which you can find running the following command in the terminal:

    udevadm monitor --environment -u | grep PRODUCT

    1.3. Disconnect or connect your iphone and you should see something like this:

    PRODUCT=2bc/12c8/520

    1.4. That's the value you put in the rules.
    1.5. Replace youruser with your own user name, by the way.

    2. Which leaves us with the /home/youruser/bin/lock and unlock scripts to create. Here is the lock script:

    #!/bin/bash
    export XAUTHORITY=/home/youruser/.Xauthority
    export DBUS_SESSION_BUS_ADDRESS=`ps -u youruser e | grep -Eo 'dbus-daemon.*address=unix:abstract=/tmp/dbus-[A-Za-z0-9]{10}' | tail -c35`
    log=/home/youruser/lock-unlock.log
    echo `date` "-" `whoami` "- Locking system..." >> $log
    su youruser -c "DISPLAY=:0 gnome-screensaver-command -a"
    echo `date` "-" `whoami` "- System locked!" >> $log

    2.1. Again, replace youruser with your own.
    2.2. You might be wondering what those lines about DBUS and the X server are all about. The reason for those is that UDEV runs stuff as root. And we want to lock and unlock the screen as our own user. Those lines make sure of that.
    2.3. For the unlock script we need to install a tool called xdotool. It's basically an automation command that allows you to make the computer type stuff and control the mouse automatically. The reason to use this is because there is no way in hell you can unlock a locked screensaver (believe me, i've tried). This tool simulates user input (moves the mouse a little bit and the enters your password and presses enter). I know it's not the most secure thing in the world but it's the only way i could make it work. Install it with:

    sudo apt-get install xdotool

    2.4. Here's the unlock script:

    #!/bin/bash
     export XAUTHORITY=/home/youruser/.Xauthority
     export DBUS_SESSION_BUS_ADDRESS=`ps -u youruser e | grep -Eo 'dbus-daemon.*address=unix:abstract=/tmp/dbus-[A-Za-z0-9]{10}' | tail -c35`
     log=/home/youruser/lock-unlock.log
     echo `date` "-" `whoami` "- Unlocking system..." >> $log
     export DISPLAY=:0
     xdotool mousemove 0 0 && xdotool type yourpassword && xdotool key Return
     echo `date` "-" `whoami` "- System unlocked!" >> $log

    2.5. Replace youruser with your own user and yourpassword with your user password.

    3. Reload the UDEV rules with:

    sudo udevadm control --reload-rules

    4. And now when you disconnect your phone from the computer, it should lock it. When you plug it back in it should unlock.

    5. Happy hacking!