No Clean Feed - Stop Internet Censorship in Australia

Ruby

Content relating to the Ruby language.

Fixing UUID generation on DreamHost

Dreamhost recently changed their configuration (at least on our server) to prevent users from running ifconfig. This causes UUID generation to fail, with an error like this showing up in the Rails log:

An exception was thrown while generating the temp path. all of /sbin/ifconfig /bin/ifconfig ifconfig ipconfig /all failed.

Long story, short form: the uuid Gem relies upon the macaddr Gem, which in turn uses one of the above binaries to determine the MAC address of the machine it's running on. So if you can't execute ifconfig (or ipconfig if you're on Windows) then UUID.generate will fail.

There are two possible fixes. Either you can change your code to use the uuidtools Gem, which seems to work nicely without being able to run ifconfig. Or, you can tell the macaddr Gem what the MAC address is in your environment.rb file:

require 'uuid'

# Specify a MAC address because Dreamhost doesn't allow us to run ifconfig.
Mac.mac_address = '00:1f:e0:8c:0f:23'

Either works - I think the former is a better way of doing it (or you'll be modifying your environment.rb file for every machine to which you deploy) but the latter is certainly faster if you're in a hurry.

My first real-world LISP code

I have deleted The GitHub repositories referred to in this post; see Clearing the deck for details.

I sometimes find myself with the need to close all unmodified buffers in Emacs that pertain to files (not all buffers do pertain to files; e.g. some contain terminal sessions).

I could have done this with M-x kill-some-buffers but this prompts for each buffer; what I wanted was something that would just silently kill any file buffer that didn't have unsaved changes.

So I wrote the following, and added it to my duncans_emacs repo on GitHub.

(defun duncans_emacs:kill-unmodified-buffers()
  "Kill any unmodifier buffers that are inspecting files."
  (interactive)
  (mapcar 
    '(lambda (buf)
      (if (and (buffer-file-name buf) (not (buffer-modified-p buf)))
        (kill-buffer buf)))
    (buffer-list)))

(provide 'kill-unmodified-buffers)

For those unfamiliar with Elisp (the LISP dialect that Emacs is mostly written in):

  • mapcar takes a lambda function and a list, then runs the lambda function against each element of the list in turn.
  • interactive lets Emacs know that this function can be called by the user using M-x.
  • buffer-file-name returns nil if the buffer in question doesn't pertain to a file (for example, a buffer that contains a terminal).
  • Elisp doesn't have namespaces, so the function name is prefixed with the package name (duncans_emacs) to avoid collisions.

After finishing this, it dawned on me that LISP isn't what I'd call intuitive or easy to read (although this might improve with time as I'm still a rank LISP beginner). An equivalent script for an (hypothetical) Ruby-based editor might look something like this:

# Kill any unmodifier buffers that are inspecting files.
def kill-unmodified-buffers
  buffer_list.each { |buf|
    buf.kill() if (buf.file? && !buf.modified?)
  }
end

(This is assuming that there's a method by which the parent class can identify user-callable functions). Now I'll concede that LISP has many positive attributes. Terseness and similarity to written English are not two of those, however :-)

Helping out over at RailsForum

Every day I'm at work, I'm going to try to answer one unanswered thread over at RailsForum. The idea is to keep my skills sharp across all areas of RoR, to help to keep the Rails as helpful and friendly as it's currently known for being, and of course to boost my own & my company's profile on the 'net.

Andelys - the power user's media player

Project information is here and I've also put up a screencast; together these should give you an idea of what I'm trying to build. Bear in mind it's very early days yet; what you see here is pretty much all it can currently do.

HOWTO: Debugging Rails tests with rdebug

Let's take a contrived & hypothetical example that's easy to follow. I have a method which is supposed to add two numbers and return the result, or 10, whichever is higher. But when I run it ...

duncan@duncan-desktop:~/demo$ rake test:units
(in /home/duncan/demo)
/usr/bin/ruby1.8 -Ilib:test "/usr/lib/ruby/1.8/rake/rake_test_loader.rb" "test/unit/calculator_test.rb"
Loaded suite /usr/lib/ruby/1.8/rake/rake_test_loader
Started
F
Finished in 0.027942 seconds.

1) Failure:
test_add_to_max_of_ten_limits_to_ten(CalculatorTest)
[./test/unit/calculator_test.rb:6:in `test_add_to_max_of_ten_limits_to_ten'
/home/duncan/demo/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/testing/default.rb:7:in `run']:
<10> expected but was
<11>.

1 tests, 1 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/usr/bin/ruby1.8 -Ilib:test "/usr/lib/ruby...]

(See full trace by running task with --trace)

The first thing I need to do is install the ruby-debug gem:

duncan@duncan-desktop:~/demo$ sudo gem install ruby-debug
Successfully installed ruby-debug-0.10.1
Installing ri documentation for ruby-debug-0.10.1...
Installing RDoc documentation for ruby-debug-0.10.1...

... and then test that it's been installed:

duncan@duncan-desktop:~/demo$ rdebug --version
ruby-debug 0.10.1

If you see an error like rdebug: command not found then you'll need to add your gem bin directory to your PATH. On Xubuntu I added the following line to ~/.bashrc:

export PATH=$PATH:/var/lib/gems/1.8/bin

Back to the code; now I can add a breakpoint to the calculator model. To add an rdebug breakpoint all I need to do is call debugger; in this case I'll make it conditional upon the two parameters totalling to more than 10:

class Calculator < ActiveRecord::Base

def self.add_to_a_max_of_ten(a, b)
result = 0
debugger if a + b > 10
if result > 10
result = 10
end
result = a + b
return result
end

end

Then I run the test through rdebug:

duncan@duncan-desktop:~/demo$ rdebug test/unit/calculator_test.rb
test/unit/calculator_test.rb:1
require File.dirname(__FILE__) + '/../test_helper'
(rdb:1)

The debugger breaks automatically at the start of the test; I can make it continue easily enough:

(rdb:1) continue
Loaded suite test/unit/calculator_test
Started
/home/duncan/demo/app/models/calculator.rb:6
if result > 10

Right, now I'm at the point where I can start examining the program flow and figuring out why it's failing. Firstly, what's the value of result at this point?

(rdb:1) var local
a => 5
b => 6
result => 0

Ohhhh, right. That might be the problem. So, where am I again in the source? I can take a look at the source with the list command:

(rdb:1) list =
[1, 10] in /home/duncan/demo/app/models/calculator.rb
1 class Calculator < ActiveRecord::Base
2
3 def self.add_to_a_max_of_ten(a, b)
4 result = 0
5 debugger if a + b > 10
=> 6 if result > 10
7 result = 10
8 end
9 result = a + b
10 return result

At this point, I can see what's going to happen - the interpreter will skip to line 9, perform the addition, and return whatever the result is. But being the cynical soul that I am (when it comes to anything electronic) I can verify this by stepping over the next few lines, and verify the result before it's returned:

(rdb:1) next
/home/duncan/demo/app/models/calculator.rb:9
result = a + b
(rdb:1) next
/home/duncan/demo/app/models/calculator.rb:10
return result
(rdb:1) var local
a => 5
b => 6
result => 11

So now, I can go on to fix the method, and verify the fix by observing that the test passes.

Playing around with Ruby metaprogramming

Recently I've started using Ruby for general-purpose scripting and small apps on Linux, and I'm enjoying it a lot. However I've been parsing command line arguments in the 'old way' that hasn't changed much since the days of C. It works, but it's not particularly elegant. Back when I switched to .NET from C, I wrote NArg as a .NET-esque implementation of command-line argument parsing ... surely it couldn't be that hard to do the same for Ruby?

The short answer is that I've been playing with metaprogramming in Ruby for a while now and no, it doesn't look like it'll be too hard (thanks in no small part to some excellent tips from Ola Bini). If, like me, you're used to non-dynamic languages it might take a few seconds for the beauty of this to sink in ...

module Kernel
def singleton_class
class << self; self; end
end
end

module Args
def has_argument(name, default)
singleton_class.send(:define_method, "cli_#{name}") do
default
end
end
end

class App
extend Args
has_argument 'somearg', 'default'

print "#{cli_somearg}\n"
end

Sure enough, when you run it, you get the following written to console ...

default

This is the conceptual basis I'll be using to build my CLI parsing module - dynamically building CLI parsing code into classes that need it by using mixins and metaprogramming. And yes, I'm 100% certain that such a thing must already exist ... but the point here is to become completely familiar with Ruby metaprogramming, even if I will have reinvented the wheel in the process Smile

Syndicate content