RudyGems

Matthew Rudy Jacobs
see me swim
Github
see some of my code
Thought Sauce
Hire me in Hong Kong

cd -Tmp-

How do I cd to a directory starting with a hypen (-)?

# /var/folders/*whatever*/ has a folder named '-Tmp-'
$ ls
-Caches-/ -Tmp-/ 

# lets try and CD there
$ cd -Tmp-
-bash: cd: -T: invalid option
cd: usage: cd [-L|-P] [dir]

# or maybe make sure its a directory
$ cd -Tmp-/
-bash: cd: -T: invalid option
cd: usage: cd [-L|-P] [dir]

# try and escape the first -
$ cd \-Tmp-
-bash: cd: -T: invalid option
cd: usage: cd [-L|-P] [dir]

# quote it
$ cd '-Tmp-'
-bash: cd: -T: invalid option
cd: usage: cd [-L|-P] [dir]

# double quote it
$ cd "-Tmp-"
-bash: cd: -T: invalid option
cd: usage: cd [-L|-P] [dir]

# escape it in the quotes
$ cd '\-Tmp-'
-bash: cd: \-Tmp-: No such file or directory

# escape it in the double quotes
$ cd "\-Tmp-"
-bash: cd: \-Tmp-: No such file or directory

# try a "./" hack
$ cd ./-Tmp-/

$ echo "WHOOP"
WHOOP

(Source: gist.github.com)

Fed up of `bundle exec rake`? Control your `rage`!

For the past year we’ve all been happy.

rake was stable at 0.8.7

You could run

rake

In any project and it’d just work.

But now, with the release of rake 0.9.0, sometimes we get this

RudiMac:3rdhome matthew$ rake
rake aborted!
You have already activated rake 0.9.0,
but your Gemfile requires rake 0.8.7.
Consider using bundle exec.

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

And there’s a simple solution.

RAGE!

#!/usr/bin/env bash
if [ -f Gemfile ]; then
  bundle exec rake $@
else
  rake $@
fi

Either copy and paste the gist into an executable (~/bin/rage maybe)

Or follow these instructions;

git clone git://gist.github.com/1003927.git ~/rage-gist
mkdir ~/bin
cp ~/rage-gist/rage ~/bin/
chmod a+x ~/bin/rage

As long as ~/bin is in your path you should be set.

rage db:migrate test --trace

BOOM!

I forgot to commit to a feature branch!

So I just committed to master

commit b17a1fbe8f5d59c24a1f2bb50c9905f8345263f5a
Author: Jeffrey Giraffe <Jeffrey.T.Giraffe@gmail.com>
Date:   Wed May 18 18:22:22 2011 +0800
  Started work on an exciting new feature.

But I shouldn’t have.

All features should be in a “feature branch”

How do I move my commit onto a different branch?

Luckily I haven’t pushed yet.

So just start my “feature branch” right now.

git checkout -b exciting-new-feature
git push origin exciting-new-feature

Then go back to master, and undo the commit

git checkout master
git reset --hard HEAD~1

Or if there are 3 commits

git reset --hard HEAD~3

Of course, if I’ve already pushed this would be a little more tricky.

I suggest (for verbosity) you shouldn’t try to do anything fancy.

Just revert it

git revert HEAD

and humbly explain why

Revert "Started work on an exciting new feature."

This commit is not ready to be on master yet,
and has been moved onto the branch "exciting-new-feature"

This reverts commit b17a1fbe8f5d59c24a1f2bb50c9905f8345263f5a.

Boom!

Running a Test Case only when we have internet

So I have some tests for geocoding, that I want to be run live.

test "geocoding" do
  record = Address.create!(:address => "Pretty Cottage, Winding Road, Beautiful Country")
  assert_equal 51.59011, record.latitude
  assert_equal -2.995398, record.longitude
end

Of course, these will fail when there’s no internet.

My choices;

  • mock the geocoding API
  • let them fail
  • only run this test when there’s internet

I chose the latter.

How do I know I have internet connection?

Can I ping google?

system "ping -q -c 1 -t 1 google.com 1> /dev/null" #=> true / false

Complication!

the above works on OSX (where -t1 sets a timeout of 1 second)

but on Linux -t has a different meaning, and -w1 sets the timeout

Compromise: ignore timeouts for the moment

system "ping -q -c 1 google.com 1> /dev/null" #=> true / false

Stick this in a method

def requires_internet!
  if can_ping_google?
    yield
  else
    flunk "this test needs to be run when there is internet"
  end
end

Now incorporate this into our test.

test "geocoding" do
  requires_internet! do
    record = Address.create!(:address => "Pretty Cottage, Winding Road, Beautiful Country")
    assert_equal 50.0, record.latitude
    assert_equal -0.3, record.longitude
  end
end

Done.

Here’s the gist. Fork it and make it better!

I broke RubyGems.org

Yes that’s right.

I broke RubyGems.org.

No April Fools Joke! (although this did happen after midnight HKT)

… I’ve hidden the cause so they have a chance to fix it…

… but its a unicode thing …

I packaged it with gem-this, and did a `gem push` it turned out http://rubygems.org was down!

I went to bed hoping it would go away, and woke up on April 1st morning to find an email;

Hi Matthew! Looks like you just found a bug that made our homepage unhappy.

=> #<Rubygem id: 39928, name: …,

I straight up deleted that gem. Can you send or paste the gem/gemspec
with that so we can make sure this doesn’t happen again?

-Nick

So, there you go!

Rubygems.org currently can’t support unicode gem names!

Upgrading Postgres 8.4 to 9.0 with Homebrew

I hoped it’d be as simple as a `brew install postgresql`

And it almost was.

But…

RudiMac:merlot matthew$ tail -f /usr/local/var/postgres/server.log
FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 8.4, which is not compatible with this version 9.0.3.

How do I fix the data files?

Turns out there is a `pg_update` method to do this for you.

But it requires a bit of manual work.

# First of all stop the server
launchctl unload -w ~/Library/LaunchAgents/org.postgresql.postgres.plist

# backup the old data directory
mv /usr/local/var/postgres /usr/local/var/postgres.old

# now create a fresh postgres 9 data directory
initdb /usr/local/var/postgres

Now we’re ready to do the upgrade.

pg_upgrade -d /usr/local/var/postgres.844/ -D /usr/local/var/postgres -b /usr/local/Cellar/postgresql/8.4.4/bin -B /usr/local/Cellar/postgresql/9.0.3/bin
...
Upgrade complete
----------------

Boom Ting

Now just add the launch control back in and we’re off.

cp /usr/local/Cellar/postgresql/9.0.3/org.postgresql.postgres.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/org.postgresql.postgres.plist
Hong Kong Ruby Group Christmas Photo

Hong Kong Ruby Group Christmas Photo

Javascript parseInt() may not do what you expect!

I was shocked today to find I’d introduced a bug.

It manifested itself like this;

This might seem ok.

Except the “Number of repayments” is set by javascript as;

the number of days interest

less the number of days before repayment begins

Looking at the dates, the “number of days before repayment begins” should be 2.

But the difference is -6.

Something is wrong.

And the answer is here;

var date_from_field = function(field_id) {
  var field = $(“#”+field_id);
  var year, month, day;

  var date_bits = field.val().split(“-“);
  var year  = parseInt(date_bits[0]);
  var month = parseInt(date_bits[1]);
  var day = parseInt(date_bits[2]);
 
  return new Date(year,month-1,day);
};

I take a date field

<input type=”date” value=”2010-12-08” />

I grab the value

“2010-12-08”

I split it into year, month, and day

[“2010”, “12”, “08”]

I turn them into integers

[2010, 12, 0]

Then I make them into a date

new Date(2010,11,0); // Tue Nov 30 2010

No problem!

Except…

“2010-12-08” != Tue Nov 30 2010

The problem is

parseInt(“08”) == 0

parseInt(“08”, 10) == 8

“08” is 0 in octal

Always use parseInt(something, 10)

Bundler as a Gemfile dependency

Bundler is still a work in progress, so you can expect things to change.

One of these things that has changed between Bundler 1.0.6 and Bundler 1.0.7 is that the “METADATA” field has been removed.

So I’m running Bundler 1.0.7 (with no METADATA) and my colleagues are running 1.0.6 (with METADATA)

I keep getting this diff.

$ git diff Gemfile.lock
diff —git a/Gemfile.lock b/Gemfile.lock
index ec585b3..ee6ba65 100644
—- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -221,3 +221,7 @@ DEPENDENCIES
   whitelist_mail_proxy
   will_paginate!
   zipruby
-
-
-METADATA
-  version: 1.0.6

I want bundler to manage itself

# self-referential
gem “bundler”, “>=1.0.7”

And it works

but the message is a bit unpretty

RudiMac:merlot matthew$ bundle install

Fetching source index for http://rubygems.org/
Bundler could not find compatible versions for gem “bundler”:
  In Gemfile:
    bundler (>= 1.0.7)

  Current Bundler version:
    bundler (1.0.6)

Your version of Bundler is older than the one requested by the Gemfile.
Perhaps you need to update Bundler by running `gem install bundler`.

I need to use “gem install”?

I wonder if we can patch bundler to install itself.

I recommend you always have a “>= x.x.x”… just for jokes try setting

gem “bundler”, “1.0.6”

Even more Ruby in Chinese

I realised I can write even more Ruby in Chinese.

The only gotchas are;

  • don’t attempt to use Chinese punctuation (”‘=+-,。)
  • it doesn’t recognise Chinese as uppercase, so you can’t start a class or Constant name with a chinese character

So here is my code.

# encoding: utf-8

class C动物

  def initialize(名字)
    @名字 = 名字
  end
  attr_reader :名字

  def 朋友?(别的)
    true
  end

  def 吃了?
    false
  end

end

class C狗 < C动物
  
  def 朋友?(别的)
    !别的.is_a?(C马泰)
  end

end

class C人 < C动物
end

class C马泰 < C人
  
  def 吃了?(别的)
    别的.is_a?(C狗)
  end

end

我=C马泰.new("马泰")
puts "我的名字是#{我.名字}"
她=C人.new("张学敏")
puts "她的名字是#{她.名字}"

狗=C狗.new("阿财")
puts "狗的名字是#{狗.名字}"

puts "狗是我的朋友吗?#{我.朋友?(狗)}"
puts "我是狗的朋友吗?#{狗.朋友?(我)}"

puts "狗吃了我吗?#{狗.吃了?(我)}"
puts "我吃了狗吗?#{我.吃了?(狗)}"

See the full gist at https://gist.github.com/711563

Maybe I should write a plugin for rails.