04 December 2013

Getting rails 4 up and running with rbenv on Ubuntu 13.10

Brain dump warning!

This is a follow up to http://timwise.blogspot.co.uk/2013/05/installing-ruby-2-rails-4-on-ubuntu.html and is just a list of steps needed to get a clean install of Ubuntu up to speed with an existing site.
  • get a project (includes a .ruby-version file for rbenv, and a Gemfile for bundle)
    • git clone git@github.com:timabell/symbol-library.git
  • sudo apt-get install libssl-dev libreadline-dev
  • rbenv install x.x.x-xxxx
    • autocompletes, yay!
    • .. or better still reads from .ruby-version I think so you can just run `rbenv install` if you are in the project folder
  • gem install bundler
    • from the right directory so done for right ruby version
    • rbenv rehash
  • bundle
    • will install all the gems for the project
  • don't sudo apt-get install rbenv ~ doesn't provide sufficiently up to date ruby
  • gem install rails --version 4.0.2 --no-ri --no-rdoc ~ don't need this when you have a gem file with rails in it, bundle will do it for you
  • sudo apt-get install nodejs
    • for javascript runtime (rails server throwing an error without this)
  • bundle exec rails server
  • bundle exec rails console
    • needs readline (see above)
Other stuff I like in my install
This is mostly for my own reference but maybe it'll help someone else out.

25 May 2013

Unfinished hyperlinks - add a todo

Just a quick post;

href="#"   ==>   href="#todo"

I'd like to promote a change to the habit of using '#' as the placeholder for a the url of a new hyperlink when you don't yet know where it'll link to: instead set the href to "#todo". This follows the //todo pattern recognised for unfinished code, and means you can now search your codebase for any links you forgot to finish off.

<a href="#">new link</a>
   becomes
<a href="#todo">new link</a>

eg: new link becomes new link

Give all these links an alert with the following (cheers to unknown in the comments)

$("a[href=#todo]").click(function () { alert('Not implemented yet.') });

It will also give clues to any sharp-eyed testers / users that they should report a bug for you as the url will change to #todo when the unfinished link is clicked. It can often be seen in the status bar too.
This has the handy side-effect of avoiding the annoying jump to the top of the page that is the default behaviour when you click on a # link that's a placeholder.

For bonus points another little trick I like is to add a click handler with an alert to make it really obvious to any early users / testers that this is not done yet, and I've found this saves a lot of questions when you genuinely haven't finished, and also guarantees a quick bug report when you should have (not that I ever forget any of course :-D)

<a href="#">new link</a>
   becomes
<a href="#todo" onclick="alert('Not Implemented');">new link</a>

eg: new link becomes new link  <= click this to see the alert

Simple and effective.

If you agree, please help spread the word. Perhaps by retweeting my tweet



P.S. This goes hand in hand with a technique of picking points during development at which there should be no todo's left in your codebase with the exception of those with references to outstanding user story / bug numbers. I suggest before marking a user story as done, and at the end of each sprint as good points to review all todos in your codebase.

Further reading:

13 May 2013

Installing ruby 2 + Rails 4 on Ubuntu 12.04 LTS

Installing Ruby 2 + Rails 4 on Ubuntu 12.04 LTS

Update Dec 2013: You may also wish to read benkwok's blog post on installing ruby and rails. I've also posted my notes from installing for an existing project which doesn't entirely replace this post but reflects my more recent learnings.

There's a few of these blog posts around, but here's mine for my own benefit (I'm sure this won't be the last time I do it!).

If you have a packaged ruby / rails / rvm / rbenv etc installed, get rid of them all, eg:

$ ruby --version
ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]
$ sudo apt-get remove ruby

Don't use rvm; and make sure it's been literally purged from your system. It's a pain to remove as it gets into all sorts of places and even apt-get purge doesn't undo changes to the profile etc. If you want to know more about the reason for not using it then read the rbenv "why" page, it's persuasive stuff.

My recommendation from experience so far is to use rbenv to install the latest and greatest RoR (Ruby on Rails). Don't bother with the ubuntu packaged version of rbenv (from apt etc) as you'll be off the beaten track and will have to figure out the ruby-build plugin installation yourself. The local user install is painless and works well. The instructions say to make sure rvm is removed first as it's incompatible.

rbenv installation

Install rbenv into your home directory:
$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv

Set up the environment as per the (ubuntu specific) rbenv installation instructions:

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
$ echo 'eval "$(rbenv init -)"' >> ~/.profile

Unless you've done anything before, there is no ~/.profile file before hand, so the contents will then be:

$ cat ~/.profile
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Restart the login shell:

$ exec $SHELL -l

Check rbenv is now available:

$ rbenv
rbenv 0.4.0-45-g060f141
Usage: rbenv <command> [<args>]
...

Set up the ruby-build plugin (as linked in the rbenv readme)

$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

Install the necessary ssl library:

$ sudo apt-get install libssl-dev

If you don't install the openssl development libraries you get this:

BUILD FAILED
...
The Ruby openssl extension was not compiled. Missing the OpenSSL lib?




Ruby installation

Install the latest ruby (version name obtained from release info on ruby blog), takes 5-10 mins

$ rbenv install 2.0.0-p0

Now select the installed ruby as the default for your user (ref: https://github.com/sstephenson/rbenv#choosing-the-ruby-version)

$ rbenv global 2.0.0-p0 
tim@atom:~$ ruby --version
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]


Rails installation

Now as per the Rails 4 RC1 announcement install the release candidate of Rails 4 (this was the latest at time of writing). Takes 5-10 mins.
$ gem install rails --version 4.0.0.rc1 --no-ri --no-rdoc

Tell rbenv to create the new shims and see the installed rails:
$ rbenv rehash
$ rails --version
Rails 4.0.0.rc1



All done! That wasn't so hard, it was all the blind alleys that took the time.

Now use bundler as recommended in the rbenv readme to set up an app etc.

Thanks for listening :-)

Footnote: It pains me somewhat to have to use installations outside of the Ubuntu package manager, however it seems there are some grumblings about the packaged versions of the above software. Add into this that I wish to use the latest RoR on an LTS release of Ubuntu which seeing as the Rails community don't seem to provide debs / repos etc leaves a packaged version out of the question for now. I've learned previously the hard way the destructive effect of randomly installing everything you find outside the package management system of a distro so have tread carefully when creating the above information.

Further reading http://benkwok.wordpress.com/2013/08/15/install-rails-on-ubuntu-12-04-lts-with-rbenv/

02 April 2013

Java checked and runtime exceptions and how to transition

As primarily a C# programmer I've never been sold on checked exceptions, mostly seeing them as an unnecessary nuisance forcing programmers to introduce reams of boilerplate throws / try-catch blocks into their consuming code to propagate these exceptions up the stack.

Whilst coding on https://github.com/timabell/FreeTTS I was forced to deal with this personal demon.

I've read that checked exceptions are a way of making exceptions be part of the declared API for some class or library, and that it forces client programmers to handle error conditions that the API programmer knows are likely to occur (e.g. the library relies on the filesystem internally so declares it throws a IOException when calling a relevant method.

I have some sympathy with this idea and can see how it can allow for more robust code when done well. My experience has generally been that it is not handled well and the reaction is to add a lot of meaningless code or to throw away the exception and hide the problem, causing difficulties troubleshooting later.

When I've been in control of the API I've been tempted to always through runtime exceptions and avoid the problem entirely, however this time whilst working on someone else's class I came across a call to an external library that threw an IOException which I couldn't change. This made me think a bit harder about the problem. I initially thought my options were to immediately catch and rethrow as a runtime exception or to add throws IOException / throws Exception to every piece of the call chain.

I tried the latter approach of propagating the throws up through many layers, which although messy did work; right up until I hit a call within a toString() method, which is defined by Object and doesn't allow you to change the API of the method (by adding a checked exception). Incidentally I think that having toString() rely on code that could throw a file system exception like this did is a dodgy design, but that wasn't my code and would have been a large rewrite.

So after a bit of grumbling to myself I looked more closely at the fault line between the checked exception being thrown and the rest of the codebase. The existing code was just ignore the error with catch {} (shudder) and returning null, making it hard to troubleshoot a failing JUnit test.

I think the answer to the conundrum is that for each method in the chain you have to decide if callers of the method could usefully handle the error condition, or whether they could add any useful information to the stack trace to assist troubleshooting. Here's roughly the approach I've taken which I think should be illustrative:

Method that throws

String getSomething(string filename) throws IOException {
    // do some file IO
    return someData;
}

Next method up. Doesn't compile as checked exception not handled, what to do?

String loadFoo() {
    String foo = getSomething("this.txt");
    return foo;
}

In this case I don't think getSomething should be the last point in the chain as it doesn't know why it was performing the operation it was. loadFoo however knows both the resource being accessed and what the intent was, so can report an exception message that should point someone troubleshooting immediately to the source of the problem and inform them what the program was trying to achieve. Having loadFoo() declare that it throws IOException doesn't make sense as the caller shouldn't need to know how loadFoo gets its data, it's just the kind of noise that programmers dislike Java for. So the answer in my opinion is because loadFoo() is best placed to give all the useful information needed to fix the problem, it should catch the checked exception, wrap it in a runtime exception, add a useful message and rethrow it. This saves callers from needing to handle exceptions that they can't usefully deal with, whilst still providing good troubleshooting information. And yet there's still a use for the checked exceptions as getSomething() was able to declare that it new an IOException was possible but that it wasn't in a position to give enough useful information.

So the final code I ended up with looked something like this:

String getSomething(string filename) throws IOException {
    // do some file IO
    return someData;
}

String loadFoo() {
    String filename = "this.txt";
    try {
        String foo = getSomething(filename);
        return foo;
    } catch (IOException ex) {
        throw new RuntimeException("Failed to read foo from '" + fileName + "'", ex);
    }
}

Inversion of control (IoC)

A colleague of mine mentioned IoC as a problem for checked exceptions. This is an interesting point and does complicate things.

References