Archive for the ‘programming’ Category

RESTful confusion

Tuesday, April 1st, 2008

REST confuses me. I’m trying to come up with a consistent, elegant RESTful interface to a web appplication, and I just can’t understand how I’m supposed to do it while maintaining “correct” RESTful design.

I see the advantages of using REST over, say, XML-RPC. I want to use it. But I’ve got serious questions and I can’t find any answers.

At the front of my list of questions is the biggest, most basic problem – that of credentials. How the hell do you send credentials as part of a REST request?

From wikipedia:

HTTP separates the notions of a web server and a web browser. This allows the implementation of each to vary from the other based on the client-server principle. When used RESTfully, HTTP is stateless. Each message contains all the information necessary to understand the request when combined with state at the resource. As a result, neither the client nor the server needs to remember any communication state between messages. Any state retained by the server must be modeled as a resource.

REST is supposed to be completely stateless. I understand that. That means no “sessions” or login keys or cookies for the client to remember and reuse. That also means the credentials must be sent with every request if I’m understanding it right.

So where are the credentials supposed to be? In the URL? Or in the form body (assuming a POST request)? If so, what about a GET request, which doesn’t have form body? And am I to assume that all REST requests requiring credentials are supposed to go over TLS? Why do none of the examples I see have any of this in them?

Since the whole point of using this is to standardise, are there standard form names (eg for username/password) we’re supposed to use? I have never seen what I consider to be a “canonical” example of this. In fact I have never seen a RESTful system using credentials of any kind which matches the first basic rule of what “is not REST” according to the RestWiki:

What is not REST?
- Stateful systems

Any system where you do not need to send the credentials more than once is stateful by definition.

Assume that we’re going to cheat a little and implement, say, a stateful session so we don’t have to log on every single time. Should the session token go in the URL? It has to, if it’s a GET and it usually will be. Or should we be faking out cookies? Again – if the session token is in the URL (a “secret” URL) that will need to be over TLS or anyone will be able to sniff it. But how else can you do sessions over HTTP GET without cookies? HTTP BASIC AUTH?

Confused yet? Me too. Has anyone ever actually implemented a pure RESTful system in an application that requires authentication?

Ruby script to recursively svn up/git pull your sources directory

Monday, March 24th, 2008

Do you have a directory full of checkouts of other people’s projects? For reference, for contribution work, etc?

Wouldn’t you like to update them all at once?

Here’s a basic ruby script that you should run at the root level of your “sources” directory. It will go through the directory, find all the folders, check if they’re under source control (supports svn, git and bzr) and if so, attempts to update them.

It’s not very nice to look at, but it’s saved me a lot of time, and I can’t find anything similar around so I thought I’d release it here. Please tell me if you have any suggestions or improvements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env ruby
 
# Basic script to walk through all directories in a folder and perform an "scm up" on them.
# Supports svn, git and bzr
# Copyright (c) 2008 Sho Fukamachi
# Released under MIT License: http://www.opensource.org/licenses/mit-license.php
 
require 'pathname'
 
def execute(*cmd)
  begin
    cmd.flatten!
    $stdout.puts "executing: " + cmd.join(' ')
    system(*cmd)
    unless $?.success?
      fail "Command failed: " + cmd.join(' ')
       << 
    else
       << 
    end
    rescue RuntimeError
      puts "!!! command '#{cmd.join(' ')}' failed in #{}, retry manually?"
       << 
  end
end
 
 = ENV['PWD']
 = Dir.entries() # very dumb, basically an ls -la
 
 = []
 = []
 = []
 
def purge_invisible dirlist
  dirlist.delete_if do |entry|
    entry[0] == 46  # 46 is the hex number for fullstop
  end
end
 
def check_directories dirlist
  dirlist.delete_if do |entry|
    !FileTest.directory?(entry)
  end
end
 
purge_invisible 
check_directories 
puts "found directories: " + .join(' ')
 
def update_recursively dirlist
  dirlist.each do |path|
     = path
    Dir.chdir path
    if File::exists?('.svn')
      puts 'svn detected in ' + path
      execute 'svn', 'up'
    elsif File::exists?('.git')
      puts 'git detected in ' + path  
      execute 'git', 'pull'
    elsif File::exists?('.bzr')
      puts 'bazaar dected in ' + path
      execute 'bzr', 'pull'
    else
       << path
    end
    Dir.chdir 
  end
end
 
update_recursively 
puts
puts "updated in: " + .join(' ') if 
puts
puts "failed in: " + .join(' ') if 
puts
puts "unsupported: " + .join(' ') if 
puts
puts 'done!'

I know you might think it’s strange to put a copyright license on such a small script but it’s for your protection, not mine. I’ve seen copyright claims over lesser things. By explicitly releasing software code, no matter how simple, you can rest easy in its use anywhere. I wish everyone included licenses with everything; I’d feel a lot more comfortable using things I find on the net if it’s been explicitly released in this manner.

Simple irb extension script

Wednesday, March 19th, 2008

I tend to create projects as a directory, with a few files in it. I might have a classes.rb file, a Rakefile, utilities.rb, that kind of thing. And chances are, I want to access them all – and any gems they require – in irb.

I often wish I had a simple way to auto-require these gems or files on a per-project level for use in irb. MacOSX 10.5 comes with a very nice .irbrc file in /etc/irbrc, and I didn’t want to get into the game of rewriting it every time I make a new project. If you make your own .irbrc, the default one won’t load – and my editor of choice, TextMate, doesn’t show .files by default in its folder view.

So what I really want is a plain file I can put in the directory with a few requires in it. I’ll have a standard name, say, “irbx” for “irb extension”. If it’s there, anything in it will be loaded – if not, no problem. I want the script that loads it in /etc/irbrc so everything to do with irb config is in one place. And I want it super simple! Just some requires! Anything more complex, and I’ll put it in another file which is then required.

So I added a few lines to /etc/irbrc so it does what I want.

First, make a backup:

$ cp /etc/irbrc /etc/irbrc.backup

Then, add this:

## in /etc/irbrc
# Require local additions
begin
  require 'pathname'
  ext_file = ENV['PWD'] + "/irbx"
  if File::exists?(ext_file)
    eval File::read(ext_file)
    puts "extension file loaded from " + ext_file.to_s
  else
    puts "no extension file at " + ext_file.to_s
  end
end

I put it underneath “Activate auto-completion” but you can put it anywhere. I kept it inside the “unless defined” statement so it can still be overridden by an .irbrc file if chosen.

Now, if you create an irbx file like this:

## in ~/my_project_directory/irbx
require 'sequel'
require 'active_couch'
require 'classes' # local classes.rb file

and then start irb in the same directory, those libraries will be loaded. If it doesn’t exist, irb starts same as always. Excellent!

There are a zillion different ways to do this kind of thing, of course. But for me, the main priority is simplicity. Convention over configuration. If you want more, writing your own .ircbc file will override the default, including this. But for the vast majority of the time, this is exactly what I need.

Laika’s ThingFish hits 0.2.0

Thursday, March 13th, 2008

Laika’s interesting REST network filestore, ThingFish, has just reached milestone 0.2.0. The project can be thought of as a ruby-language, more flexible and lightweight implementation of LiveJournal’s MogileFS, and is actually by the same developers.

To get it running, you’ll need to do the following:

## install dependencies
$ sudo port install ImageMagick 
$ sudo gem install mp3info exifr mongrel pluginfactory uuidtools rdf-redland rmagick sequel_core sequel_model
$ wget http://prdownloads.sourceforge.net/clxmlserial/clxmlserial.1.0.pre4.zip
$ unzip clxmlserial.1.0.pre4.zip
$ cd unzip clxmlserial
$ sudo ruby install.rb
$ cd ..
## download and run thingfish
$ svn co svn://opensource.laika.com/thingfish/releases/0.2.0 thingfish
$ cd thingfish
$ chmod +x start
$ ./start

Thingfish should now be available at http://0.0.0.0:3474/.

UPDATE: To actually be able to upload a file, you’ll need to manually create the directory /tmp/thingfish:

mkdir /tmp/thingfish

UPDATE 2: Not easily usable yet. After a two-hour adventure to try and build the gem, no dice – this ticket pretty much sums it up. Sorry if I’ve spoilt the “fun” for you! UPDATE: might have a fix for this, see comments.

I’m still excited about this project, and they don’t owe me a thing, but unsatisfiable dependencies to some untagged trunk version of some guy’s library in his personal svn is not exactly good practise. I’m looking forward to getting started with a howto article or two – but if I can’t even install it as a gem with reasonable efficacy that’s not going to happen. Here’s hoping an 0.2.1 release follows soon fixing some of these showstopper issues.

UPDATE 3: Many of these issues have been fixed in trunk (thanks devs!), stay tuned for an initial howto.

Issues remain in running from trunk, at least in OSX 10.5.2. It’s currently impossible, apparently, to install the redland bindings necessary to properly load the rdf-redland gem used by ThingFish using macports. I’m unwilling to start installing stuff from source when I have a perfectly good ports system, so I’ve emailed the maintainer asking for an update and will keep on top of this.

Horrible WP export data format

Wednesday, March 12th, 2008

So, I’m writing blog software, and one of the obvious things I want to do is import from this blog. As a first step towards that, I export the entire contects using WP’s export tool (after purging more than 17,000 comment spams since I last manually purged) and this is what it looks like (previous post to this):

>
>Interesting words in your OSX Dictionary>
>https://fukamachi.org/wp/2008/03/11/fake-words-in-your-osx-dictionary/>
>Tue, 11 Mar 2008 03:03:46 +0000>
>Sho>
        >>
        >>
        >>
         domain="tag">>
         domain="tag">>
 
 isPermaLink="false">https://fukamachi.org/wp/2008/03/11/fake-words-in-your-osx-dictionary/>
>>
>>
>713>
>2008-03-11 12:03:46>
>2008-03-11 03:03:46>
>open>
>open>
>fake-words-in-your-osx-dictionary>
>publish>
>0>
>0>
>post>
        >

Jesus, that is *horrible*. Firstly, if the post_type is defined only towards the end, what’s with the post_id, post_date, post_name etc? It’s a post – of post_type post! Secondly, where’s the “updated at” field? What’s the “dc:” namespace for the creator tag only? What’s with having an “isPermalink” switch in the guid tag? The permalink is in the link tag, I presume. Why does it need to be content:encoded when obviously the content is CDATA – implying that WP somehow supports XML parsing inside some contents!? Why is pubDate camelCase while everything else is underline_style? Man, I hate camelCase. Etc etc. What a mess.

I know what you’re thinking: that’s just RSS format! Sure it’s ugly, it’s RSS! Well, no. The RSS is similar but different for this post – I examined the feed for that, too. Note that the description is empty, it isn’t in the RSS. So they’re using a modified RSS format to store internal data. If they’re not going to store description, but just generate it on the fly – why export empty description tags?!

Just for comparison, here’s the much nicer atom feed. Obviously doesn’t have all the wp: internal data, but I much prefer the design:

>
        >
                >Sho>
                >https://fukamachi.org/>
        >
         <span style="color: #000066;">type</span>=<span style="color: #ff0000;">"html"</span><span style="color: #000000; font-weight: bold;">></span>
>
         rel="alternate" type="text/html" href="https://fukamachi.org/wp/2008/03/11/fake-words-in-your-osx-dictionary/" />
        >https://fukamachi.org/wp/2008/03/11/fake-words-in-your-osx-dictionary/>
        >2008-03-11T03:04:31Z>
        >2008-03-11T03:03:46Z>
         scheme="https://fukamachi.org/wp" term="Language" />
         scheme="https://fukamachi.org/wp" term="leopard" />
         scheme="https://fukamachi.org/wp" term="mac" />
         scheme="https://fukamachi.org/wp" term="dictionary" />
         scheme="https://fukamachi.org/wp" term="esquivalience" />
         type="html">>
         type="html" xml:base="https://fukamachi.org/wp/2008/03/11/fake-words-in-your-osx-dictionary/">
                Using Leopard? Try this. Look up the word esquivalience by selecting it and choosing dictionary from the contextual menu. Read the dictionary definition, then the wikipedia one underneath : )

]]>
>
>

Note logical, consistent design, self-closing tags, and other innovations.

UPDATE: Check out the comment format:

>
>3>
>>
>>
>http://nigger.org/>
>127.0.0.1>
>2005-07-16 10:23:48>
>2005-07-16 14:23:48>
>Hey, is this that new gay nigger cock website I've been hearing about?>
>1>
>>
>0>
>

The comment author is CDATA, but the content isn’t? WTF?

Reducing LOC with ActiveRecord

Sunday, March 9th, 2008

Heh, as you can probably tell I’m going through old code with a chainsaw right now.

If there’s one thing I’ve learnt about maintainability, it’s that lines of code are the enemy. The longer a function, the less you can see on screen at once, the harder it is to understand. So with that in mind, let’s go over a few tricks you can use to shorten your code – this time in Controllers.

Have you ever done anything like this?

def create_message
  message = Message.new(params[:message])
  message.sender_id = .id # we can't trust form input
  message.language_id = .language_id
  message.something_else = Something.else
  if message_save
    redirect_to some_url
  else
   error!
  end
end

OK, this is a pretty bad example from a design perspective. Since the current user should be a model, and whose details are thus available in the Message model, it would probably be a better idea to set things like that inside the model. But let’s say we have to do it from the controller for some reason.

One limiting property of ActiveRecord is that you can’t send more than one attributes hash when you create a new object, so newbies like me when I wrote similar code to that above would create the new object and then manually append endless other properties to it before committing. And we want to keep the params hash for convenience – that’s why we’re using Rails after all!

But that params hash is just a hash, and that means we can merge with other hashes, and since we’ve got it all in one place let’s drop the .new and go straight for .create:

def create_message
  props = {:sender_id => .id, :language_id => .language_id, :something_else => Something.else}
  params[:message].merge!(props) 
  if Message.create(props)
    redirect_to some_url
  else
   error!
  end
end

Yeah, this is pretty basic stuff, not the 1337 tip you might have been expecting. But it took me a long time to get over my fear of messing with the black box of the params hash, and looking back at my old code made me remember. Anyway we dropped the LOC to get this record into the database from 5 to 3 – and it would stay at 3 no matter how much crap you added to the setup hash.

One tip won’t save you that much space, but every bit helps!

UPDATE: I had it back to front. Forgot hash merge order. >_<

Reducing code duplication with Rails ActionMailer

Sunday, March 9th, 2008

ActionMailer is a weird, fussy black box whose intricacies produce a lot of code duplication, especially for dealing with multi-language email, where you need to use a different .erb file for each language. Here’s an example of how you can reduce some of that duplication.

Code speaks louder than words so I’ll just cut and paste – you can see pretty easily what I’ve done. Works, although it’s completely undocumented and is probably not very good practise.

Previous, highly redundant code. I’ve snipped this a lot – you don’t have to use much imagination to see why I don’t like this:

def tokenmail_eng(user, subject)
  subject       subject
  body          :token => user.password_hash,
                :password => user.password,
                :user_id => user.id,
                :name => user.nickname
  recipients    user.email_address_with_name
  from          ''
  sent_on       Time.now
  headers       "Reply-to" => ""
end
 
def tokenmail_jpn(user, subject)
  subject       subject
  body          :token => user.password_hash,
                :password => user.password,
                :user_id => user.id,
                :name => user.nickname
  recipients    user.email_address_with_name
  from          ''
  sent_on       Time.now
  headers       "Reply-to" => ""
end
 
def tokenmail_zhs(user, subject)
  subject       subject
  body          :token => user.password_hash,
                :password => user.password,
                :user_id => user.id,
                :name => user.nickname
  recipients    user.email_address_with_name
  from          ''
  sent_on       Time.now
  headers       "Reply-to" => ""
end

Woah. That is *awful*. When I finally decided to clean up my mail code I found several problems even in my cut and pasted code – when you do that a few times, and then go in to make a change, you are almost guaranteed to leave something out. That is precisely why cut and pasting code is something you should never, ever do.

So how do we clean this up and merge into a “generic” mail, while fooling ActionMailer into using the correct file?

Turns out we can do this:

def tokenmail_gen(user, subject)
  subject       subject
  body          :token => user.password_hash,
                :password => user.password,
                :user_id => user.id,
                :name => user.nickname
  recipients    user.email_address_with_name
  from          ''
  sent_on       Time.now
  headers       "Reply-to" => ""
end
 
def tokenmail_eng(user, subject)
 tokenmail_gen(user, subject)
end
 
def tokenmail_jpn(user, subject)
 tokenmail_gen(user, subject)
end
 
def tokenmail_zhs(user, subject)
 tokenmail_gen(user, subject)
end
 
def tokenmail_zht(user, subject)
 tokenmail_gen(user, subject)
end

That’s so much better it brings a tear to my eye. Needless to say you will need to handle translation of the subjectline in your Controller.

SERIOUS NOTE: This is undocumented and while it seems to work, I haven’t heard of anyone else doing it and it might not work in future. Use at your own risk and make sure your tests cover it!

Eval, friend and enemy

Sunday, March 9th, 2008

The prevailing wisdom in the Ruby world is that using eval is bad. It’s brittle, hackish and inflexible – if you find yourself using it, it’s usually a sign you’re doing something wrong.

Well, I agree, but the keyword is “usually”. Sometimes using eval is a lot better than any alternatives, and it can help work around problems in, say, other people’s code, where the design decisions they made stop you doing what you want. I avoided using it for a long time, maybe based on my acceptance of the consensus opinion – but recently I’ve had cases where it’s the “lesser of two evils”, and I wanted to share one with you.

The example is Rails’ horrible mailing system. It’s one of the worst parts of Rails – but let me temper that by saying it’s a hard problem and difficult to see how else they could have done it. A Mailer in Rails is kind of a pseudo-model black box that waits to be sent a list of parameters, then inserts some of them into a specific text file, then sends that text using the remainder of the parameters.

All very well and good so far. But the problem with this is when you want to have mail in multiple languages. So you don’t just have

Notifier.deliver_welcome_mail(params)

you have

Notfier.deliver_welcome_mail_eng(params)
Notfier.deliver_welcome_mail_jpn(params)
Notfier.deliver_welcome_mail_spa(params)

etc. All with corresponding entries in the model, and matching text files.

Now, I don’t know any way to get around the need for those text files and entries in the model that doesn’t involve writing some huge text generator (bad) or hacking Rails itself (even worse). But we can at least improve on the statements used to call these deliveries.

Here’s an example of what I used to have:

if .language_iso == 'zht'
  Notifier.deliver_invite_zht(, , subject)
elsif .language_iso == 'zhs'
  Notifier.deliver_invite_zhs(, , subject)
elsif .language_iso == 'jpn'
  Notifier.deliver_invite_jpn(, , subject)
else
  Notifier.deliver_invite_eng(, , subject)
end

That’s a shortened version of what can be much longer if or case statements (this is pretty old code..). But you can see this gets very nasty, very quickly.

Using eval we can change that to:

eval("Notifier.deliver_invite_#{.language_iso}(, , subject)")

Yes, it’s still nasty. But it’s one line of nastiness as opposed to 10 (or many more). I think this is one example of a case where using eval is definitely better than the alternative.

Next, I’m experimenting with trying to reduce the horrendous duplication in the Mailer pseudomodel itself.

Strict databases are great for discipline

Friday, February 8th, 2008

Oh, boy. Nothing exposes one’s shitty programming habits like using a new, stricter databse like PostgreSQL. All over the place I’m discovering, and fixing, code in which I’d demonstrated a lax attitude to data integrity – from trying to insert invalid data into columns I’d previously specified should not be null (datetimes, mostly) to declaring booleans with 1 or 0 instead of true and false.

It’s annoying, sure, but it’s also quite satisfying. A database that won’t take any shit is great for your programming discipline and must lead to better, more reliable code. I really can’t believe how much MySQL allows you to get away with, and I’m very glad my eyes were opened to the problems with the data I was storing before I had to manually repair million-line tables in production.

I have discovered a few annoyances with PostgreSQL, though – just to be fair. Its sequence system is pretty silly – after importing data you have to then go and explicitly set new sequence numbers for any autoincrement fields (PgSQL calls them “serials”). A useful facility but I think the default should just be to increment the sequence on import. I have of course written a script to automate this but still.

Another complaint is regarding the security, which if anything seems *too* strict. When you use Schemas to share logical databases between multiple users, any user but the owner of the “foreign” schema must have privileges granted explicitly on not only every table they plan to use in that schema, but on the aforementioned sequence tables too! I can understand the first, kind of, although there should be an option to grant privileges at the schema level, but the second is just silly – if you have rights to add new rows to a table, it is implied you should also have rights to increment the sequence. A needless bit of complexity.

That said, I’m overall delighted with the migration and everything was up and running fine. It’s not now, since I decided to completely excise my nasty multi-database hacks and simplify the data structures, removing all potential conflicts and separating tables into their logical homes. I’m about half way through doing that. And again, I’m really happy that I’m doing this now – what may take a day or two with development-stage databases might take weeks to do with live production servers – not to mention all the code that would have been built on top of the original suboptimal data structure. I’d actually been just about to write a whole lot more of that – something I’d actually been putting off because I knew what a mess the databases were, and was reluctant to dig myself any deeper a hole – but now I’m really looking forward to flying through what should be a much simpler, more intuitive job.

ActiveRecord::Base.find(:last) in Rails 2

Thursday, January 17th, 2008

I don’t know about you, but when I see find(:first) I also expect there to be a find(:last). This hack was working in Rails 1.x but broke in Rails 2. So I fixed it. Paste this into environment.rb or wherever:

module ActiveRecord
  class Base
    def self.find_with_last(*args)
      if args.first == :last
        options = args.extract_options!
        find_without_last(:first, options.merge(:order => "#{primary_key} DESC"))
      else
        find_without_last(*args)
      end
    end
 
    class << self # Needed because we are redefining a class method
      alias_method_chain :find, :last
    end    
  end
end

I wouldn’t rely on this in actual production code (for a variety of reasons) but it’s a useful convenience method for script/console, which is where I tended to want this functionality anyway.

>> MyTable.find(:all).length
=> 2076
>> MyTable.find(:first).id
=> 1
>> MyTable.find(:last).id
=> 2076
>> puts "1337"
1337
=> nil

Never, ever use IronRuby

Wednesday, December 26th, 2007

So, you’ve heard of IronRuby? Microsoft’s implementation of Ruby on .NET. I’m hearing a bit of talk about it around the interwebs. Thinking of trying it out, eh?

Don’t. Ever.

Microsoft invented the technique we now refer to as Embrace, Extend, Extinguish. They tried it to Sun Java (MS JVM). They’ve tried it with Kerberos, and even today every web developer in the world is frustrated, wasting time trying to get around MS’s attempts to poison HTML and CSS.

A Leopard doesn’t change its spots. There is only one conceivable reason for Microsoft to implement another language on its own platform, and that’s that it sees it as a threat and wants to kill it. First, make a really good implementation! Fast, easy, Visual Studio! Next, “improve” it – on Windows only, of course! Third, we’re using MS Ruby++ and we’re fucked.

Run a million miles from IronRuby. If you assist in giving it traction, if you feed it any attention at all, you’re just making the world a worse place for all of us.

And one would be advised to think very, very carefully before adopting any technology – or, just as importantly, any *implementation* of a technology – that is not open source from top to bottom. GPL is best but MIT will do.

May MS never stain the history of computing again…

RubyConf 2007 videos online

Wednesday, December 26th, 2007

I didn’t realise that the entire RubyConf 2007 video archive is now online here. Some really good talks there.

Video may seem a poor teaching format, but sometimes I just get tired of reading all the time – and picking up some of the personality of the speaker can be very instructive and convincing. A good presentation can be interesting, educational, and steer you in a direction quite impossible with self-selected study which, almost by definition, only teaches you what you were already looking for. Watching what someone else has to say, and what they think is important, can be really interesting.

It’s great to live in a world where gigabytes upon gigabytes of good-quality conference video are available online, for free.

And there’s other conferences on that site as well – I’m still working my way through, but the Jamis Buck segment at Mountain West, Rails Code Review, was fascinating. I respect Buck a lot – hell, he’s basically second in command, and so I’m very interested in hearing what his views are on what is and isn’t good coding practise.

Check it out.

Ruby 1.9 released!!

Tuesday, December 25th, 2007

See http://www.ruby-lang.org/ja/, it’s not on the English site yet, nor is it tagged in SVN.

Awesome! : )

UPDATE: it’s on the english site now, but still not tagged in SVN.

I wonder what the “best practise” method of upgrading in OSX would be?

Rails not working yet on Ruby 1.9 trunk

Saturday, December 15th, 2007

For those entranced by these benchmarks results and wanting to host Rails on Ruby 1.9 ASAP …

My testing shows Rails 2.0.1 failing on current svn/trunk installs of Ruby 1.9 on MacOSX 10.5.1.

But WEBrick works!

Ruby 1.9 build:

cd ~/src
svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby-1.9
cd ruby-1.9
autoconf
./configure --prefix=/usr/local/ruby1.9
make
sudo make install
cd /usr/local/ruby1.9/bin/
./ruby -v
-> ruby 1.9.0 (2007-12-15 patchlevel 0) [i686-darwin9.1.0]

Rails 2.0.1 installation:

pwd
-> /usr/local/ruby1.9/bin
sudo ./gem install rails
-> Successfully installed actionpack-2.0.1
-> Successfully installed actionmailer-2.0.1
-> Successfully installed activeresource-2.0.1
-> Successfully installed rails-2.0.1
-> 4 gems installed
-> Installing ri documentation for actionpack-2.0.1...
-> Installing ri documentation for actionmailer-2.0.1...
-> Installing ri documentation for activeresource-2.0.1...
-> Installing RDoc documentation for actionpack-2.0.1...
-> Installing RDoc documentation for actionmailer-2.0.1...
-> Installing RDoc documentation for activeresource-2.0.1...
$

All installs nicely …

Attempting to run a Rails app (after install a few more requisite gems using above method):

$ cd /rails/my_1337_app/
$ /usr/local/ruby1.9/bin/ruby script/server
=> Booting WEBrick...
/usr/local/ruby1.9/lib/ruby/gems/1.9/gems/activerecord-2.0.1/lib/active_record/associations/association_proxy.rb:8: warning: undefining 'object_id' may cause serious problem
/usr/local/ruby1.9/lib/ruby/gems/1.9/gems/rails-2.0.1/lib/initializer.rb:224: warning: variable $KCODE is no longer effective; ignored
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-12-15 07:24:35] INFO  WEBrick 1.3.1
[2007-12-15 07:24:35] INFO  ruby 1.9.0 (2007-12-15) [i686-darwin9.1.0]
[2007-12-15 07:24:35] INFO  WEBrick::HTTPServer#start: pid=3386 port=3000
 
## I request http://0.0.0.0:3000/ ... 500 Internal Server Error
 
Error during failsafe response: can't convert Array into String
127.0.0.1 - - [15/Dec/2007:07:24:52 EST] "GET / HTTP/1.1" 500 60
- -> /

OK, it bombs out trying to actually process a request. But this error is really, really fast! I am actually serious saying that, the error *is* really fast.

Mongrel installation fails:

$ sudo ./gem install mongrel
Password:
Building native extensions.  This could take a while...
ERROR:  Error installing mongrel:
        ERROR: Failed to build gem native extension.
 
/usr/local/ruby1.9/bin/ruby extconf.rb install mongrel
creating Makefile
 
make
gcc -I. -I/usr/local/ruby1.9/include/ruby-1.9/i686-darwin9.1.0 -I/usr/local/ruby1.9/include/ruby-1.9 -I.  -fno-common -g -O2 -pipe -fno-common  -c fastthread.c
fastthread.c:13:20: error: intern.h: No such file or directory
fastthread.c:349: error: static declaration of ‘rb_mutex_locked_p’ follows non-static declaration
/usr/local/ruby1.9/include/ruby-1.9/ruby/intern.h:556: error: previous declaration of ‘rb_mutex_locked_p’ was here
fastthread.c:366: error: static declaration of ‘rb_mutex_try_lock’ follows non-static declaration
## etc etc etc

So webrick’s all we have for now.

You can track the state of edge Rails’ 1.9 readiness in this ticket on the Rails Trac. Plugins, though, will be another matter, although some fixes are pretty easy; an early failure I’ve seen is with plugins using File.exists?('file') which is of course deprecated in 1.9 in favour of the far, far superior File.exist?('file').

I like using the 1.9 console, though – it really does feel snappier, especially to load irb!

Migrations much improved in Rails 2

Friday, December 14th, 2007

I hadn’t been using migrations much in Rails 1.x. I just didn’t like the workflow – it was too clumsy, and I got annoyed at writing out the files. The workflow in 1.x was as such:

1.

script/generate migration MigrationName [--svn]

2. go and manually edit 00x_MigrationName.yml in /db/migrations to reflect your desired database changes, both up and down:

class AddCreatedAtToStaff < ActiveRecord::Migration
  def self.up
    add_column :staff, :created_at, :datetime
  end
 
  def self.down
    remove_column :staff, :created_at
  end
end

3. rake db:migrate to apply the changes to the local database.
4. svn commit and cap deploy:migrations to apply the changes to the remote database

Too long – especially step 2. I knew I should do it in principle, but CocoaMySQL is right there – especially if you make several changes in the space of a few hours. In theory it’s best practise – but in actual practise someone as lazy (and impatient) as me tends to just do it directly in the DB, then eternally put off that day where they’ll finally “move to migrations”.

It’s not even the laziness – it’s the “flow”. I’m doing other things, I’ve realised I need this field. I don’t want to stop what I’m doing and write out a damn YAML file! I want the field there, right now. Too demanding? Maybe, but like I said, the DB is right there, and the difference between a 5 second edit and 2 minutes writing the file is a lot of lost concentration.

And various other solutions, such as auto_migrations, seemed good but in practise are too flaky and a dangerous, unsupported road to take.

Enter Rails 2.0, and migrations are far, far better. The core Rails principle of “convention over configuration” is in full effect here, with excellent results.

Now the process of adding a migration is as such:

1.

script/generate migration add_created_at_to_staff created_at:datetime [--svn]

Note the convention at work here. You’re implicitly telling Rails the table to use, in this case “staff”, and the field you’re adding – in this case one of Rail’s magic “created_at” fields. You then explicitly write the fields out, which you’d have to do anyway in CocoaMySQL or similar, or manually at the mysql command line.

2. rake db:migrate to apply the changes to the local database.
3. svn commit and cap deploy:migrations to apply the changes to the remote database

That’s only one step less, but it was the biggest and most annoying one. The actual creation of the migration file and addition to svn is now a single brief, easy-to-remember line. This is now terse enough and convenient enough to enter my personal development workflow, a very welcome improvement to the framework, and an excellent demonstration of Rails’ core principles in action.

Resolve conflict between jQuery and Prototype

Thursday, December 13th, 2007

I had a strange error where Prototype and jQuery were overwriting each other’s namespace. Please don’t ask me why I happen to using both – it’s just on one page, and it’s just until I work out how to duplicate my Prototype effort in JQ (I find JavaScript utterly incomprehensible and incredibly difficult to learn).

Anyway, I tried a number of tricks with loading order and including various bits of each. I couldn’t keep it working – either I had one or the other, never both. Then I read this page: Using jQuery with Other Libraries on the official jQuery developer pages. It recommends you do as such:

   <script>
     jQuery.noConflict();
 
     // Use jQuery via jQuery(...)
     jQuery(document).ready(function(){
       jQuery("div").hide();
     });
 
     // Use Prototype with $(...), etc.
     $('someid').style.display = 'none';
   script>

But I don’t have any Prototype script in HEAD. It’s all addressed through the default Rails includes. I didn’t want to start messing with that.

I implemented the above, it didn’t work but the failure was different – now Prototype was trying to work, but erroring out with prototype TypeError: Value undefined (result of expression $) is not object.

Solution: On a lark, I removed jQuery.noConflict(); and renamed all jquery-targeted $(function) shortcuts to jQuery(function):

   <script>
     jQuery(document).ready(function(){
       jQuery("div").hide();
     });
   script>
 
// in body: Ajax.new & co Rails commands

It’s a horrible nasty hack that gets around the horrible nasty problems from using two JS frameworks on the same page. Don’t copy this, I’m posting it only for your morbid curiosity. If you dare copy this horrible technique your Good Programmer’s Card is revoked. But it works!

BAC

Thursday, November 29th, 2007

This is so, so, so true. I thought I was the only one …

There are other axes (pronounced /ˈækˌsiːz/) too – amount of time since last interruption, amount of time since last sleep, availability of music, drinks, cigarettes …

.rhtml vs .erb

Monday, November 26th, 2007

post_update <<-EOF
Can the people who read this rant please remember that this is not a very serious blog. In fact it’s mostly just me talking shit and this post is a prime example. I actually like the changes I’m dissing below, it’s nothing but a rant for rant’s sake and I have no idea why Google seems to be sending so many people to it – so don’t get all upset and leave nasty comments telling me I’m an idiot.

This is a personal blog of the most whimsical and useless kind, and I make no pretensions otherwise. Bear that in mind. Thanks! :-)
EOF

Can someone please tell me what the point of moving from .rhtml to .html.erb is?

I mean seriously. There wasn’t a naming conflict, .rhtml isn’t the nicest extension on earth but it was pretty unambiguous as to what it was – ruby mixed with HTML.

.html.erb is if anything worse. What kind of a file has TWO extensions? Hell, why not have fucking ten. I sometimes like to put CSS and JS into my files as well, they’re feeling a bit left out – I guess that according to this new “all inclusive” philosophy they’re properly named index.html.css.js.erb.

And what the fuck does ERB even stand for? Embedded Ruby, right? Well that would be great if Ruby was two words. One acronym per word is the English standard. Yet another example of Rails flaunting the standards.

I just don’t see the point. Trying to enforce a taxonomy on what are by nature highly mixed and variable files is an exercise in futility. And furthermore, the .erb is completely superfluous within the already highly structured folder structure of a Rails app. What the hell else would it be?

Change for change’s sake. DHH is drunk on power!

Ruby: quotes are different

Tuesday, October 23rd, 2007

I cannot tell you how many times this has tripped me up.

1
2
3
4
5
6
>> str = 'fuka'
=> "fuka"
>> str2 = '#{str}machi'
=> "\#{str}machi"
>> str2 = "#{str}machi"
=> "fukamachi"

Supposedly the ruby interpreter is faster using single quotes, because it doesn’t have to read the string first looking for possible substitutions within. But I dislike using double quotes on aesthetic & number-of-keystroke grounds so inevitably do this again, and again, and again.

I wonder if there’s a way to simply force ruby to always interpret single quotes as double. The few times I need to escape something in the string, I’ll do it manually – it’ll be worth it to reduce confusion like this:

1
2
3
4
5
6
username = 'sho'
endpoint = Net::HTTP.new("localhost", 8888)
headers = {'Content-Type' => 'text/javascript'}
response = endpoint.post("/shadow/_temp_view", 'function(doc) 
{ if (doc.username=="#{username}") { map(null, doc.username); } }',
 headers)

Quick, tell me if #{username}’s going to be substituted properly or not.

Installing CouchDB on MacOSX

Monday, October 8th, 2007

If you, like me, have been keeping an eye on the extremely interesting CouchDB Project then maybe you’ve thought about playing around with it a bit on your Mac. This turns out to be very simple.

I assume you have macports w/ subversion (and XCode, of course) installed already. Most of this comes straight from the Readme but I hate reading those, I just want someone to write what I have to do – maybe you do too, so here you are!

UPDATE: 11th October

Reinstalling after noticing 60 commits in 3 days .. now that’s active development.

(more…)