RudyGems

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

Ruby in Chinese

in Ruby 1.8, if you try and assign a variable

你=”ni3”

you’ll get an error

Invalid char `\344’ in expression
Invalid char `\275’ in expression
Invalid char `\240’ in expression
syntax error, unexpected ‘=’
你= “ni3”

But in Ruby 1.9 it actually works.

You just need to add a magic “coding: uft-8” header to your ruby file.

# coding: utf-8
你= “ni3”
好= “hao3”
puts(你+好)

Wham!

matthew@RuPro:~$ ruby chinese.rb
ni3hao3

(if you can’t write chinese, steal my gist http://gist.github.com/613670)

How to delete a file from Git History

I always think about this problem;

What happens if I accidentally commit my password into a git repository?

Surely it’ll be there forever?

Or

Oh man… I just committed a 700mb video file into the repository

It’s going to take forever to deploy…

I’ve always known “get rebase” will probably be the answer

Luckily ProGit knows exactly what to do. 

git filter-branch —tree-filter ‘some-bash-command’ HEAD

So here’s my example of how to use it.

I’ve accidentally added a picture of my bum to this rep.

$ git show 84c344
commit 84c344c1874736a6d063ed45abe21e20815525b9
Author: Matthew Rudy Jacobs <MatthewRudyJacobs@gmail.com>
Date:   Wed Sep 15 18:25:35 2010 +0800

  add my bum

diff —git a/mybum.jpg b/mybum.jpg
new file mode 100644
index 0000000..018be38
—- /dev/null
+++ b/mybum.jpg
@@ -0,0 +1 @@
+a picture of my bum

so let’s try and wipe it from history.

$ git filter-branch —tree-filter ‘rm -f mybum.jpg’ HEAD
Rewrite 76a50a3b1b3263d84517c8e6241ec0bf2bf36fdc (4/4)
Ref ‘refs/heads/master’ was rewritten

now commit 84c344 is still there, but it is not in our branch.
Looking at git log, I can see it’s been rewritten to f59366

$ git show f59366
commit f59366420a8b753de5a0d2812e0abbfb95fccfdf
Author: Matthew Rudy Jacobs <MatthewRudyJacobs@gmail.com>
Date:   Wed Sep 15 18:25:35 2010 +0800

    add my bum

so my bum is no longer there. In the working tree, or in history.

Right now DON’T git pull it will merge your commits with the original commits.

You’ll have achieved nothing (except doubling the number of commits)

I don’t have an elegant solution… but this seems the only way.

delete all remote repositories

and push to them again

I’m sure there’s a better way… but I haven’t found it.

Here’s my example repo http://github.com/matthewrudy/git-rebase-test

go play!

git pp (git push && git pull)

I am addicted to committing (not commitment).

I make small, distinct commits all the time.

But the consequence of this is

$ git push origin master

To git@myServer:myRepo.git
  ! [rejected]        master -> master (non-fast-forward)
  error: failed to push some refs to ‘git@myServer:myRepo.git’

To prevent you from losing history, non-fast-forward updates were rejected

Merge the remote changes (e.g. ‘git pull’) before pushing again.  See the
‘Note about fast-forwards’ section of ‘git push —help’ for details.

I hate getting push failures.

But I don’t trust myself to do a pull beforehand.

Enter a git alias!

$ cat ~/.gitconfig
[alias]
    pp = !sh -c ‘git pull $0 $1 && git push $0 $1’

Now I am free to “git pp origin master” as much as I want.

$ git pp origin master

From myServer:myRepo
 * branch            master     -> FETCH_HEAD
Already up-to-date.
Everything up-to-date

SAFE!

OR logic in gmail filters

I don’t want to have to read all the emails from my old job,

but I do want to read some of them.

So the obvious answer is using gmail filters, to tag, and archive the ones I don’t want.

It turns out the emails I don’t care about are sent to

notifications@somedomain.com and something-notify@otherdomain.com

I guess it makes sense, but in the filter box we can use the “OR” keyword

notifications@somedomain.com OR notify@otherdomain.com

Boom ting!

Stop adding methods to Symbol just to make your DSL look pretty!

I remember the first time I saw Datamapper.

I liked saying “:something.gt something_else”.

It was pretty.

But after a while I realised it wasn’t necessary.

So why are we still building APIs that involve extending Symbol?

I saw this on an extension called Plucky for MongoMapper

Ruby Enterprise Edition still faster than Ruby 1.9.2?

With Ruby 1.9.2 due to ship on July 31st, I thought I’d take Ruby 1.9.2 preview 3 for a spin.

A quick…

rvm install ruby-1.9.2-preview3

gem install rails prawn erubis

… and we’re done.

But is it any faster than REE?

What does it mean to be faster?

Perhaps all I care about is how fast my tests run

rvm use ruby-1.9.2-preview3

time rake

rvm use ree

time rake

# repeat..

My app:

  • Rails 2.3.6
  • rails_xss
  • postgres
  • ~25 models
  • ~25 controllers

My test suite:

Results;

So REE is consistently 10% faster at running my test suite than Ruby 1.9.2-preview3

Does this matter?

Probably not… but maybe I can use those extra 5 seconds.

(can’t wait to see if the Phusion.nl guys can make Ruby 1.9.2 faster… )

ssh -D is your friend!

Are you stuck behind a firewall?

Does your work block access to facebook?

Do you want to watch English Telly from abroad?

SSH -D is your friend.


All you need to bypass the firewall;

  • ssh access to a VPS
  • ssh -D8080 me@myserver.com // keep this open
  • go to your browser
  • set “connect via SOCKS proxy” on port 8080
  • keep the ssh connection open
  • voila!

Your internet access is now piped via your VPS.

This means;

  • if it is in the UK you can access iPlayer
  • if it is in the US you can access Hulu
  • if you were in China you can access… everything

Boom ting!

Rails 3 doesn’t allow “open” as a Named Scope

Rails 3 has involved rewriting pretty much the whole codebase,

Rails 3 gives off the fragrance of a coherent, cohesive framework.

But this one kind of annoys me.

/Users/matthew/.bundle/ruby/1.8/bundler/gems/rails-16a5e918a06649ffac24fd5873b875daf66212ad-master/activerecord/lib/active_record/named_scope.rb:104:in `scope’: Cannot define scope :open because AbcDef.open method already exists. (ArgumentError)

So, in Rails 3, when defining a named scope, we can’t override an existing method.

This all makes sense, we don’t want to inadvertently break anything (although I’d hope your test would catch such a thing)

But unfortunately, every object in Ruby has an “open” method… so “open” suddenly is off the market for named scopes… bummer

I spent most of day trying to sort this out… writing a patch… trying to convince people to apply it… but the rails core guys wouldn’t budge.

So here’s a quick hack I put in an initializer

# config/initializers/allow_open_as_a_named_scope.rb
require 'active_record'
class ActiveRecord::Base
  class << self
    alias :_open :open
    undef_method :open
  end
end

And we’re done…

Kind of annoying though. I use “open” all the time, because it makes sense

I’d prefer it if active record just made a logger.warn, and let me make my own decisions

My Fork of rails, My Example of the bug, My Undef_Method hack

Securing CruiseControl.rb on Nginx

CruiseControl is great

Quick and easy to setup

But takes a few minutes to work out how to secure it.

we start cruise;

cruise@MerlotBuild:~/cruisecontrol.rb$ ./cruise start -d
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://0.0.0.0:3333

Going directly by IP http://94.102.144.37:3333 we get our cruise install.

But that’s not good enough, we need to secure it from the outside world

In Nginx we do this;

server {
  listen 80;
  server_name cruise.matthewrudy.com;
  
  auth_basic "Access";
  auth_basic_user_file /opt/nginx/conf/htpasswd;

  location / {
    proxy_pass http://localhost:3333;
  }
}

And we’re almost done

Except http://94.102.144.37:3333 still works, as mongrel allows requests from any host name

cruise@MerlotBuild:~/cruisecontrol.rb$ ./cruise start -d -b 127.0.0.1
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://127.0.0.1:3333

Does the job… home… secure… safe?

How big is my MySQL database?

mysql> SELECT table_schema,
sum(data_length) / 1024 / 1024 "data",
sum(index_length) / 1024 / 1024 "index",
sum( data_length + index_length ) / 1024 / 1024 "total"
FROM information_schema.TABLES
GROUP BY table_schema \G;

*************************** 1. row ***************************
table_schema: aardvarks_development
data: 5297.32812500
index: 4407.93750000
total: 9705.26562500
*************************** 2. row ***************************
table_schema: aardvarks_test
data: 0.09375000
index: 0.25000000
total: 0.34375000
*************************** 3. row ***************************
table_schema: badgers_development
data: 13.59375000
index: 16.60937500
total: 30.2031250

as you can see, aardvarks_developpment is almost taking up 10gig

if we only care about “test” databases, we can add a condition on “table_schema”

mysql> SELECT table_schema,
sum(data_length) / 1024 / 1024 "data",
sum(index_length) / 1024 / 1024 "index",
sum( data_length + index_length ) / 1024 / 1024 "total"
FROM information_schema.TABLES
WHERE table_schema like "%_test"
GROUP BY table_schema \G;

*************************** 1. row ***************************
table_schema: aardvarks_test
data: 0.09375000
index: 0.25000000
total: 0.3437500

Boom!

(credit to Paul Butcher for the query)