OK, I admit it. I have finally acknowledged that web design is something I should not waste my time on.
The design of this site has gone through several phases, all my own attempts and none that I was satisfied with. So yesterday I finally bit the bullet, jettisoned my old home grown styles and images and resorted to Twitter Bootstrap.
Whilst a quick glance reveals the obvious use of Twitter Bootstrap, I’m encouraged by the result. I can now rely on a popular, well-designed, well-documented tool to produce an acceptable looking site rather than struggling with my own incompetence. For me, Twitter Bootstrap hits the sweet spot. After all, it is aimed at programmers who don’t have good web design skills.
For those interested in what it took to convert a Rails site to use Twitter Bootstrap, here are some of the steps I followed:
One aspect I’m delighted with is the fact that Twitter Bootstrap supports responsive design out of the box. I’ve found it interesting that one of the barriers to adding content to this site has been it’s poor display on mobile devices. Not only did the site look ugly, but it didn’t facilitate easy browsing on mobiles.
Not any more. As a by-product of using Twitter Bootstrap, my site is now responsive!
Having used Twitter Bootstrap before, it was a fairly painless exercise to convert the site. All it took was a rainy day on a long weekend to finally encourage me to bite the bullet.
Now I have one less excuse for writing blog posts!
Phew! I’ve just about recovered from Rails Camp 9, an event that may be described as an unconference. It took place over the June long weekend at Lake Ainsworth near Byron Bay on the NSW far north coast.
For this camp, it was my honour to be one of the organisers. Fortunately, Rails Camp now has a well-established pattern and there were many organisers of previous camps willing to help and advise. And I had a terrific team amongst whom to share the workload.
Nevertheless, for the benefit of future Rails Camp organisers, I thought I’d share a few recollections of how our team went about organising Rails Camp 9.
I present the wonderful bunch of Rails hackers who all played their part in ensuring that Rails Camp 9 was, to use an over-used adjective du jour, awesome: Jason Crane, Scott Harvey, Zubin Henner, Ben Hoskings, Tim McEwan, Elle Meredith, Keith Pitty and Jason Stirk. (Trivia note: half of this crew were at the inaugural Rails Camp at Somersby in 2007.)
How did we choose the venue? Once we had settled on the idea of holding Rails Camp in the Byron Bay area, the locals in the organising crew – Zubin Henner, Elle Meredith and Jason Stirk – scoured the region looking for a suitable venue and came up with only one that could accommodate the numbers we were expecting.
In many respects Lake Ainsworth was a perfect venue. Nestled between the lake and the beach it had excellent facilities for our needs. The staff were very helpful and I can really only think of two negatives: we were obliged to deal with some unexpected government bureaucracy and we had to hold the camp on a long weekend.
Settling on the venue was half the battle. Happily, as this photo shows, we were also able to organise the essential ingredients of Rails Camp.
Thanks go to Zubin for organising the beer and Elle for organising the coffee machine. As for the coffee itself, Jason Crane ensured we had excellent beans and well trained baristas!
Speaking of essential ingredients, securing the services of Ben Hoskings to again set up the server and wifi was wonderful. Apart from one brief power outage during the weekend, everything ran as smooth as clockwork. So coffee, beer and wifi were sorted, ensuring happy campers!
Some of the other things we did to keep the organisation on track leading up to the weekend were:
One of the wonderful things about an unconference such as Rails Camp is that, once it starts, it is largely self-organising. The 146 participants of Rails Camp 9 decided how they would spend the weekend. Many chose projects to work on and talks to either present or listen to. Some simply appreciated the opportunity to socialise amongst like-minded people. And, of course, there were games of Werewolf to be played.
As an organiser, once the camp had started, I found my role was largely to be alert to the possibility of requests for assistance. Whilst this did keep me reasonably busy I did have the chance to catch up with and meet lots of Ruby people from around Austalia and New Zealand. I also managed, thanks to Phil Oye, to remember how to use Bananajour so that I could submit a couple of patches to Ideagora. And, there was one particularly epic game of Werewolf (thanks Carl) to remember.
A wrap of Rails Camp 9 would not be complete without thanking our sponsors. So, on behalf of the organising crew, I extend a big thank you to:
Another heartening thing about the Australian Rails Camp community is that by the end of one camp a volunteer invariably steps up to take responsibility for organising the next camp. Happily, Sebastian von Conrad did just that at Lake Ainsworth, agreeing to take possession of the virtual baton to ensure that Rails Camp 10 happens near Adelaide.
Not only that, there have already been discussions about the possibility of Rails Camp 11 in Queensland and Rails Camp 12 in Tasmania!
Last night I deployed a new release of a Rails app.
Having deployed apps built with Rails 3 or at the very least Rails 2 apps using Bundler, the experience of deploying a Rails 2.3.5 app left me with a keen desire to at least bring this app up to Rails 2.3.11 with Bundler.
One of the delights of last night’s deployment was having to update RubyGems on the target machine. Usually this is as simple as:
gem update --system
That is, unless you are forced to upgrade to a specific, old release of RubyGems. Being at Rails 2.3.5 with this app, we were in this situation.
Speaking of “not exactly state of the art”, the version of Ruby on the target machine is Ruby Enterprise Edition 1.8.6.
Obviously, the preferred option would be to upgrade to Ruby 1.9.2 and Rails 3.0.5 forthwith.
However, it’s not my money that will be funding the upgrade. First steps first. I’m aiming for the following path:
Wish me luck!
It was long overdue.
Rails 3.0.5 is out and I’ve finally bitten the bullet and upgraded this site to Rails 3 and Ruby 1.9.2. The site had its genesis back in mid-2007 as I was preparing to start my own business. Since 2008 the codebase hasn’t received much love. Indeed, I have only published articles here in dribs and drabs over the last couple of years.
So, as I embarked on this upgrade, I was aware that it also represented an opportunity to clean up some of my code as well as update third party libraries.
What follows is a story of how the upgrade unfolded including some decisions I made along the way and some lessons I learned.
My initial intention was to just upgrade the app to use Ruby 1.9.2 and attack the Rails 3 upgrade later. However, as I soon found out, getting the app to work on Ruby 1.9 wasn’t as easy as I had anticipated. Sure, using RVM it was easy to change to using Ruby 1.9.2 in development. I also chose to move to Bundler even though my intention was to stay at Rails 2.3 for now.
However, I quickly discovered that not all the plugins I was using had been upgraded to run on Ruby 1.9.
Back in 2008 when I implemented syntax code highlighting I chose to use the tm_syntax_highlighting plugin, which is based on Ultraviolet. Unfortunately, the original tm_syntax_highlighting plugin is not supported on Ruby 1.9. There is a gem derived from it that claims to support Ruby 1.9 but I failed to get this to work.
I had a look at the suggestions from Ryan Bates and, because I had been using a solution based on Ultraviolet, I considered using Harsh but soon found that it was not supported on Ruby 1.9.
At this point I decided to go the whole hog and upgrade to Rails 3. As for supporting syntax highlighting, I ended up switching to use CodeRay.
First point of call for anybody embarking on a Rails 3 upgrade has to be Jeremy McAnally’s Rails 3 Upgrade Handbook. This invaluable resource not only guides you through using the official “rails upgrade” tool but explains how to make the most of the improvements in Rails 3.
So I methodically worked my way through the upgrade to the point where I was able to start and use the Rails console. This was a real milestone but I still had much to do before I could consider my upgrade complete.
When I attempted to get the app running via a browser it quickly became evident that it was high time I jettisoned some ancient plugins.
Chief of these was the acts_as_authenticated plugin. Yes, I did say ancient. I’m aware that Devise is a favoured authentication solution for Rails 3. However, having had success in other projects with Authlogic, I chose to use it in the interests of expediency.
Another old plugin that needed replacing was acts_as_taggable_on_steroids. The acts_as_taggable_on gem proved to be an effective replacement for this with minimal changes required.
The final old plugin to be jettisoned was akismetor, which I replaced with the Rakismet gem.
I haven’t said anything about automated tests to this point. That is quite simply because I haven’t touched them. I know I should but, since this is a relatively small app that really only affects me, I decided to bypass automated testing in favour of completing the upgrade quickly. Some may scold me for this decision but I couldn’t justify the effort to myself. I’ll come back and get the automated tests working again later.
Note: If this was a larger app for a customer I would be far less inclined to bypass the task of ensuring that the automated tests work before considering the upgrade complete.
I’m glad I’ve taken the time to upgrade this app to Rails 3 and Ruby 1.9.2. It has given me the chance to:
And, of course, now I can say that I have upgraded an old Rails app to Rails 3!
I think it’s time I gave a brief update about a couple of professional events within the Australian Ruby community that I’ve recently enjoyed.
Last month over an extended weekend the fifth Australian Rails Camp was held in the Queensland Gold Coast Hinterland. The venue was superb, much fun was had and a great deal of thanks is due to the Brisbane contingent who organised the event.
Having started the weekend working on my own to improve my iPhone development skills, particularly with respect to using ObjectiveResource to integrate an iPhone app with a Rails backend, I was actually very pleased that I didn’t continue on this path beyond Saturday afternoon. From Saturday evening onwards I teamed up with Martin Stannard and Michael Koukoullis to develop a Heroku-like tool called Bivouac. I thoroughly enjoyed our collaboration and learnt much from it. For anyone else considering attending a future Rails Camp I thoroughly recommend getting involved in a team project rather than working alone.
More on Bivouac in a later post. Meanwhile, you can find the source on github.
Earlier this week the monthly Sydney RORO (Ruby on Rails Oceania) meeting featured a dozen lightning talks. In one of my talks I shared a technique for providing XML in a legacy format via REST, XML Builder and a presenter object. Whilst the example is contrived, the technique is one that I used to handle a requirement for a client recently.
Here are the slides:
In fairness, I must give credit to Obie Fernandez for his coverage of XML Builder in his book, The Rails Way, which gave me a head start.
I encountered a trick for young players the other day when providing XML-RPC web service support within a Rails application.
Since Rails 2.0 was introduced, RESTful web services via ActiveResource have been supported in preference to SOAP or XML-RPC web services. Indeed, ActionWebService was dropped from Rails when version 2.0 was released.
However, there are times when the need to provide an interface to another application mandates the use of SOAP or XML-RPC. Recently I had a need to provide an XML-RPC web service server within a Rails application. Fortunately, a version of ActionWebService has been kept up to date on GitHub together with instructions for implementing it.
As I was developing my support for XML-RPC calls, I found chapter 25 of Thomas and Hansson’s “Agile Web Development with Rails” (second edition) invaluable.
For simplicity’s sake, let’s say my controller was:
class BackendController < ApplicationController wsdl_service_name 'Backend' web_service_api BackendApi web_service_scaffold :invoke if Rails.env == 'development' def foo_bar(args) # method code goes here end end
And here is an XML-RPC test client:
require 'xmlrpc/client' require 'pp' server = XMLRPC::Client.new2("http://example.com/backend/api") result = server.call("FooBar", ["arg1", "arg2", "arg3"]) pp result
Notice that the call is to a method called “FooBar” whereas the method within the Rails controller is called “foo_bar”. If you’re like me you will have originally fallen into the trap of assuming that the remote call will have the same name as the controller method rather than the camel case equivalent.
I think I’ve just about recovered from last weekend’s Rails Camp in the Adelaide Hills. Whether I was hacking or socialising, as the hour got later each evening it just seemed easier to ignore the fact that I was going to pay later for the lack of sleep.
It was worth it though. This was the best attended Rails Camp yet with about 70 Rails developers converging from different parts of Australia. One of the aspects I like about these events is their self-organising nature. The unconference style encourages learning within small groups for much of the event. In my case I was determined to practice using Cucumber, Webrat and Machinist and benefited from the fact that several others were also cutting their teeth on Cucumber.
There are also plenty of opportunities to share with the whole group. At this camp I was fortunate that Pete Yandell, the author of Machinist, was one of those who spoke. I also thoroughly enjoyed the lengthy discussion which was precipitated by Pat Allan’s talk about Freelancing.
Quite apart from the learning opportunities, I appreciated catching up with other Rails developers I hadn’t seen for a while and making new friendships. I’m looking forward to my next Rails Camp already. Hopefully the number of attendees doesn’t increase. I think it has reached its limit for a good unconference.
I’ve sometimes wondered why CSS isn’t more dynamic.
Take, for example, the styles applied to the sub-menu on the services page of this site. To achieve the highlighting of the current service, I combine a Rails view and CSS as follows:
<div id="<%= @current_service.name %>"> <div id="secondaryNav"> <ul> <% @services.each do |service| %> <li class="<%= service.name %>"><%= link_to service.heading, service_path(service) %></li> <% end %> </ul> </div> </div>
#agileweb #secondaryNav .agileweb a, #java #secondaryNav .java a, #coaching #secondaryNav .coaching a, #mentoring #secondaryNav .mentoring a, #overview #secondaryNav .overview a, #advice #secondaryNav .advice a { color: #99CC00; text-decoration: underline; }
That does the trick nicely until I decide to add a new service. Wouldn’t it be nice to have that CSS regenerated dynamically whenever I create, update or delete a service?
Enter a new Ruby module:
# lib/dynamic_css.rb module DynamicCss def generate_services_nav_links_css return if RAILS_ENV == "test" FileUtils.cd File.expand_path("public/stylesheets", RAILS_ROOT) File.open("servicesnav.css", "w") do |out| service_names = [] services = Service.find :all services.each { |s| service_names << s.name } service_names.each_with_index do |name, i| out.print "##{name} #secondaryNav .#{name} a" if i + 1 < service_names.size out.puts "," else out.puts " {" end end out.puts " color: #99CC00;" out.puts " text-decoration: underline;" out.puts "}" end end end
Then a small adjustment to invoke the css regeneration via a filter in my admin services controller:
class Admin::ServicesController < AdminLayoutController include DynamicCss after_filter :generate_services_nav_links_css, :only => [:create, :update, :destroy] # remainder of controller end
Lastly, to ensure that the servicesnav.css file exists by the time one of the public services pages is requested:
# config/initializers/services_nav_css.rb include DynamicCss generate_services_nav_links_css
Admittedly this is a specific case, but this example shows that it is relatively straightforward to dynamically generate CSS within a Rails app if required.
agile bundler capgun capistrano community conferences consulting css deployment design development approaches dsl estimation jaoo javascript legacy apps osdc pdf planning prawn rails railscamp rbenv reflections resources rorosyd ruby ruby australia ruby tracker rubyconf_au rubygems rvm standups syntax highlighting testing twitter bootstrap unconference wds08 web design xml yow