The intersection of technology and leadership

Category: Ruby

Managing Ruby Development Environments

One of the principles I like is being able to set up new development environments very quickly. The java space offers many libraries for managing your environment that means that each project works in a separate space. In contrast, in the .Net space an anti-pattern is one that often requires many installs to your GAC (Global Assembly Cache) often through the use of a “mouse-driven”-only installer.

Fortunately the ruby community offers a number of tools for managing both versions of ruby and the libraries that you use. The ones that I will often reach for, now include:

  • RVM – Ruby Version Manager. Allows you to have different versions of ruby, and to quickly switch between them
  • Bundler – Management of gems.

The ultimate acceptance test for this, is can developers simply “check-out” and go. The lead time to setup a new development environment should be very quick.

Note that there is now a competing tool for managing environments called RBenv although integrated tool support (like in RubyMine) is only starting to come through

USB Programming with Ruby

I have a current side project of looking for a simple to construct build radiator that is reasonably affordable from a hobbyist’s point of view. I came across this blog post, that used a sub £10 USB device for displaying the state of monitors. Although good, the drivers only appear to work on linux (not on my mac!) but I decided to not let that stop me.

I spent a couple of hours yesterday reading up on USB, the options around ruby (my current project’s development language of choice) and then the source code for the linux drivers written in C++. Here’s proof that I managed to learn a few things:

Outlining some of the things that I learned:

  • Two ruby libraries exist for wrapping the generic libusb library that vouches to be cross platform (win, linux, mac). The first “ruby usb” is one that I couldn’t get working on my machine partly because I couldn’t configure it properly to read my installing libusb. I went for the libusb (for ruby) library. This proved easier as they already had a gem for it.
  • The generic USB interface is pretty well documented. This website gives a good overall introduction. The concepts translated into the library quite easily.
  • At the heart there are some simple steps, but if you plan on controlling a device, you need to know the special “byte” messages to send as instructions. I don’t have an electrical engineering background, but I’m guessing this is similar when they write device drivers. Having documentation helps (this is where looking at the device driver code helps).
  • The libusb gives some pretty reasonable error codes, and because my device simply does not respond, I didn’t have to worry so much about any other processes controlling it at the same time.

Generic steps for interacting with a USB device:

  1. Create a new USB context to discover all the devices
  2. Find the device you care about. For this device, the property idVendor is set to 0x1d34 for Dream Cheeky and the idProduct set to 0x0004). They also had some string descriptions you could use. For example, the manufacturer property returned "Dream Link" and the product returned "DL100B Dream Cheeky Generic Controller"
  3. Once you have the device you first “open” the device to get a “handle”. Your system may already have a reference to it. If so, you need to “detach the kernel driver” before claiming it. As I said, I didn’t need to although the linux driver has that code in it.
  4. With the handle, you can now send/receive information to it. The USB property “bmRequest” prepares the device for communication. This page really helped me understand more, although I simply followed what the linux driver did to know what values to set.
  5. Make sure you close the handle when you’re done.

I learned way more than I needed to about USB devices such as devices hosting several configurations (though only one at a time) and they have a concept of endpoints, but wasn’t particularly relevant. Debugging the device with irb was great fun as I could dynamically query the device as long as it was connected. I’ll write about the ruby code in a different blog post.

Tapping into dynamic programming with Ruby

I had a task to analyse the value of a cookie set by a tool on the subdomain. The value of the cookie set looked something like this:

"18337|20120404|True#Q0A|18342|21-30|20120404|18344#Q1|18349|NO PARTNER|20120404|18351#Q2|18352|EMPLOYED|20120404|18353#Q4|18432|STRUGGLING|18539|WANT|20120404|18541#Q3|18358|EMPLOYED|20120404|18359#"

My task was to try to decipher the values of set inside the cookie and how they changed depending on the progress through the application that set the values. I was told the answers to questions sat next to the ID of the question. For example, the answer to the “age” question (21-30) was related to the question 18342 and would always appear as |18342|21-30|. I started out with some tests and ended up with a method like this:

class Answers
  attr_accessor :age, :employment_status, :has_partner

  def parse(cookie_contents)
    items = cookie_contents.split("|")
    items.each_index do | i |
       current = items[i]
       if (current == "18342")  
         @age = items[i+1]
       elsif (current == "18352") 
         @employment_status = items[i+1]
       elsif (current == "18349") 
         @current_partner = items[i+1]
       end
    end    
  end
end

Of course, I wanted to avoid the growing if-else statement so found a way that I could do it dynamically and focus just on the mapping from an ID to an attribute. The resulting code looked like this:

class Answers
  attr_accessor :age, :employment_status, :has_partner
  
  Mappings = {
    "18342" => :age=, 
    "18352" => :employment_status=, 
    "18349" => :has_partner=
  }  

  def parse(cookie_contents)
    items = cookie_contents.split("|")
    items.each_index do | i |
       current = items[i]
       if (Mappings.has_key?(current))
          self.public_send(Mappings[current], items[i+1])
       end
    end    
  end
end

By the end of the analysis, I discovered that multiple IDs mapped to the same properties and all I had to do was add another entry into the map defining which ID mapped to what property on the object. With java/.net being more of my background, I was pleased to see how brief the code turned out to be.

Ruby Script to Capture HTTP traffic

I spent some time early this week trying to debug why some test was failing. It was using RESTeasy and I wanted to find out exactly what HTTP packets it was sending. If I was on a windows machine, I’d look towards Fiddler, but I couldn’t find anything easy on mac, so I wrote a little ruby script that I could point the client at and dump out all headers and request body.

It looks like this:

require 'webrick'
include WEBrick

class Simple < WEBrick::HTTPServlet::AbstractServlet
  def do_POST(request, response)
    puts "Body: " + request.body
    puts "Header: " + request.raw_header.to_s

    response.status = 200
  end
end

server = HTTPServer.new(:Port => 5899)
server.mount "/", Simple

['TERM', 'INT'].each do |signal|
trap(signal){ server.shutdown }
end

server.start

Update
Upon publishing this, I got a couple of alternatives worth looking into for next time.

  • Jim suggested using tcptrace; and
  • Gaz suggested using the following command sudo tcpdump -vvv -A -s 0 -i en1 tcp ‘port 5899’

This is just yet another example about why it’s important to have diversity when problem solving. I didn’t even know about these tools. Now I do and you do too.

UK November Away Day

I’ve been lucky enough to attend two of Thoughtworks‘ Away Days over the last month. Most recently I attended the UK Away Day this weekend that provided a great opportunity to catch up with some people and generate some new ideas. I’d write up more about the Indian Away Day I’d attended two weeks prior, but running a two week training course almost immediately has taken away my time to reflect and my memory’s a little foggy these days.

Here’s an overview of the sessions that I attended:

  • A Lessons Learned session applying Ruby on Rails – An interesting session presented by Paul Ingles and George Malamadis about their approach to building a fully functional website with some of the pitfalls. I love these sorts of sessions as you get the insight into the decision making processes with talk about the constraints and thinking that pushed patterns into the direction of the end result. Really nice and a great topic to start leading into the Meta Programming session later than evening.
  • The Space Within – Hosted by the very calm Manoj Ramachadran who ran through a number of exercises to help improve the “quiet” times in our lives and give us an ability to become more effective. I found this interesting as it gave me insights into other methods to try.
  • Features of C#3.0 – Presented by Troy Gould and a great statement opening it along the lines of C#3.0 is included in .Net 3.5. How confusing is that? An interesting code example comparison by comparison of features new to C#3.0 introduced to support Linq. I think pretty much everyone was thinking how these features could be used effectively, and where they would be more likely (ab)used.
  • Case Study of a Consulting only session – An ever excitable and interesting co-presentation with Luke Barrett and one of our clients where the focus wasn’t directly about delivering working software, but focusing on delivering value even earlier by clarifying a business case and helping evaluate its feasibility. I enjoyed hearing the application of the same lo-fi techniques and methods bringing value in a different space for once.
  • Meta Programming – A fun session running through features of Meta Programming in Ruby by Farooq Ali and Julie Yaunches. I really enjoyed this session, and glad I could attend this since I’ve had the pleasure of working in the same room with both of these people and they’re passion for Ruby really shone throughout the presentation. They reminded me of the power language gives, and definitely helped me refine some thoughts I’d been having about the environment or approach needed to pull this off successfully.

I had a great time catching up with loads of people and had plenty of fun after the conference gathering at Sway.

© 2024 patkua@work

Theme by Anders NorenUp ↑