Design Patterns In Ruby

Design Patterns In RubyDesign Patterns In Ruby

  • Russ Olsen
  • Programming

A few years ago I didn't know that design patterns existed when writing software. It was only when I started tinkering with Ruby, because of Rails, that I heard about a book called Design Patterns : Elements of Reusable Object-Oriented Software written by the mythical sounding "Gang of Four".

Whenever I've been writing Ruby code in the past I've always had the nagging feeling that I'm doing it wrong. There is obviously more than one way to tackle a problem but I never know if I've taken the correct path. Countless blog posts have been devoted taking a class, or a method, and re-factoring it, making it leaner and cleaner. I guess the only way to learn is to write it so that it works, then go back to it over time and re-factor it. Surprisingly, after reading this book, that's what I'm doing now to one of my little Ruby projects.

The book takes 14 of the classic patterns and considers them from the point of view of Ruby code. It covers the background and basic Ruby concepts and idioms in the first part before launching into patterns. The third part discusses patterns for Ruby and looks into the Rails code.

For a book that is so heavily code related it is surprisingly easy to read away from the keyboard. But to really understand how the code works you would need to run and tweak it to see what makes it tick. That's what I intend to do next.

A book to always keep near you for those times when you feel that someone must have dealt with this coding problem before.


Rails Magazine

Today I received my copy of the first Rails Magazine in the post. I haven’t read it yet, so don’t expect an in-depth review. But it did bring back memories.

When Santa, via my parents, delivered my Sinclair ZX81 back in the early eighties he gave me a copy of Your Computer with the ZX81 on the cover. The magazine contained letters, reviews, articles and, most importantly, code samples that you could type in. Just like Rails Magazine. So for a few years I would get it delivered every month from the paper shop. But one magazine wasn’t enough so I also used to get Computer and Video Games magazine. This, as it’s title suggests, really only contained programs dedicated to the fun side of computing. I spent many happy hours trying to type in programs for the Pet and the Vic20 only to discover that they wouldn’t have a hope in hell of running.

Some readers where obviously a dab-hand at a black art known as machine code. To do this on the ZX81 you had to create a REM statement on the first line to contain the program, so it had to be exactly the right size. Then you would type in a loader program and enter the hex characters. Before you ran it you had to make sure it was saved, to cassette tape naturally, because once it was running the only way to stop it was to kill the power.

One evening I had spent about half an hour typing these characters in. They had to be 100% accurate or the program wouldn’t run. Someone opened the bedroom door and, being of a nervous disposition, I jumped, knocking the ZX81 with the 16k ram pack and lost everything that I had spent so long typing in.

After that came the Dragon 32 and Dragon User magazine. I think that I'd ditched Computer and Video Games by then, being more of a serious programmer.

Back before downloads, cover mounted DVD ROMs, CD ROMs and both floppy disk formats I remember getting programs on a floppy vinyl 45rpm record. This contained about 4 programs for different computers and you recorded the sound onto audio cassette and loaded it in as you would a program that you had saved yourself. Ah, happy days!


Caching

Who would have thought that this site would need to use page caching? Well, to be honest, it doesn’t. The one Mongrel cluster was rendering the pages absolutely fine. The site doesn’t get a whole heap of hits. But after watching the Rails Lab screencasts by Gregg Pollack on tuning and optimizing Rails applications, I decided to give it a try.

The Advanced Rails Recipes has two good recipes, Preserve Files Between Deployments and Segregate Page Cache Storage with Nginx, which along with screencasts helped a lot. I was only ever going to venture into Page Caching as the posts and the pages remain static.

All in all it was really easy. I knew about symlinking using Capistrano so it was just a case of setting my Enki fork to use page cache for the index and show actions for posts and pages. The problem I had wasn’t with the caching, which worked fine, it was with expiring the pages if they are changed. Enki has the administration controllers in a sub-folder so for some reason I couldn’t just use expire_page post_path(post) in the post sweeper, to get around that I just had to build up a string matching the post path manually, expire_page "/#{year}/#{month}/#{day}/#{slug}". There is no doubt a way around that using routes, but I haven’t found it. So if I add a post, it will zap the main index page, the archives page, the tags page and also the page of any tags that are associated with the new post. Simple. The only other problem was with the Nginx config settings. I had to change the ones in the book slightly to use $document_root instead.

Before I deployed the caching changes I added the RPM Lite from New Relic to see the response times. Apart from the occasional, self-induced, spike it was all running fine. The /posts/show controller action was taking the most time, essentially the rendering, but looking at the stats post-caching the slowest controller action is the sitemap, and I guess I could cache that.

Now that the site is running completely from static HTML pages it makes me wonder why I bothered setting up the database, Rails app, capistrano, directories etc when I could have just run it on my iMac and rsynced the changes up to the server. In fact that’s really how this site started. I just had an index page with server-side includes dragging in dated post entries.

When Brent Simmons described his publishing system earlier this year I found it really inspiring. No databases, no code (as least running on the server), easy to backup, just templates and scripts run locally and synced to the web-server. That’s all you need. Nothing big, nothing fancy. Of course, I wanted to learn more about Rails by using it on a live site… and it has been lots of fun.


All Change

All ChangeAll Change

Yes, it’s all change… again.

For the first time, in a long time, this site has switched engines. Previously it used WordPress but now it’s using a Ruby on Rails blogging application called Enki. I haven’t stopped using WordPress entirely as the website for my Uncle Les is still running very well on the latest 2.7 release.

I had spent a month or so trying to write my own from scratch, and did manage to get something working, but I kept finding that I was struggling to get the basics polished off. Enter Enki, which is just a barebones blogging app that you can build upon.

So, I've removed (or at least commented out) the comments section of code. I might resurrect commenting on the site but, as I've found previously, it’s much more trouble than it’s worth. I've switched to Markdown for markup instead of textile. I don’t quite know why, just that I read http://daringfireball.net/ all the time. The only other ‘behind the scenes’ changes are a switch to FeedBurner for the RSS feed (so update your reader) and I've used Google Custom Search in a similar way to the WordPress set-up that I had.

My Advanced Rails Recipes book came in really handy when it came to generating a sitemap, creating custom error pages and a different maintenance page. I’ll be using more of the recipes in that book in the future.

The style of it all is just really simple and is based on the 960 Grid System. I'm only really using the grid for the basic layout at the moment, but I shall use more of it as I add to the site. What are the chances that it becomes as cluttered as the last in no time.

I still have a few things to fix. The book reviews are still all in HTML because Markdown thinks that because it contains a ‘div’ that it isn’t needed. Rspec tests don’t pass because I've changed some code to get the book reviews to use a different partial etc.

Just consider it a work in progress which can be found in all it’s glory at github.com.


Deploying Rails Applications

Deploying Rails ApplicationsDeploying Rails Applications

  • A Step-by-Step Guide
  • Ezra Zygmuntowicz, Bruce Tate and Clinton Begin
  • Programming

Before I even wrote a Rails application I wondered exactly how this would be run on a remote server. Especially a shared server that you didn't even have command line access to. The first Rails book that I read didn't really cover that aspect in any great depth as I recall. So, I constantly thought exactly how would this work. If I wrote a great application would I have to pay big bucks just to get it working.

Up until now I think I have spent much more time getting Rails to work on a remote server than doing any actual coding.

I tried getting getting Rails to work on Bluehost, which at the time, didn't work. Then I had a Mephisto site running on TextDrive using Lighttpd, which did work, but I really didn't know enough about what was involved as I had just blindly set it up using the instructions they provided. Now I've switched to SliceHost, I set-up the slice using the Deprec gem, then had trouble using Capistrano and Subversion to deploy an application. So I set-up another slice and transferred things over. Now I have an application, that only I use, which was running Apache2 and a Mongrel Cluster but is now running Apache2 and Phusion Passenger™ (a.k.a. mod_rails/mod_rack). It's no wonder that I've only just started to move about Rails development.

To be honest, it's all good fun. Except when things don't work the way you expect and you have no idea why. If you are developing Rails applications, even like me as more of a hobby, then you need to know about the environment that it's going to be running on.

This book covers it all from hosting, shared, virtual and dedicated, to Capistrano set-up, which you will certainly need to understand to remove deployment headaches. Then it covers Mongrels, Apache2 and nginx and even has a section on deploying to Windows, for those who like pain or simply don't have a choice. There are also chapters on clustering MySQL, database sharding and performance benchmarking.

Because the book was only released this year it doesn't cover mod_rails. From a recent Web 2.0 Show podcast that Ezra was on I can understand why the book had to be rewritten three times, just to keep up with the latest advances in hosting environments.

It is a book I wish I had either bought sooner, or that it had been released earlier. At least now I have a book that I can use as a guide. I still want to aim to have either a slice, or an S3 instance that is running nginx, mongrel cluster with monit and that's all.

Everything that you wanted to know about Rails deployment... but was afraid to ask.


Everyday Scripting with Ruby

Everyday Scripting with RubyEveryday Scripting with Ruby

  • for Teams, Testers and You
  • Brian Marick
  • Programming

After, what must have been, the third attempt I finally worked through this book.

You would have thought that with writing little Ruby scripts for myself, and for work, that zipping through it would have been a breeze.

The book is essentially similar to the pick-axe book, but less detailed obviously, and with more exercises. And it's these exercises that I had trouble with. If you are following along at home, which I and the book encourage you to do, you have to complete them all. This is because the work that you should have done in the previous chapter will be touched upon in the next chapter. Sometimes you think, "Yes, I can do this, I understand it, I don't need to code this", only to find that parts of the next exercise rely upon it. I think if each set was more self contained it would have worked better.

The chapters do cover the Ruby basics, with real-world examples and tasks, then the subjects get trickier as the book goes on. I don't think for a minute that I understood inheritance and superclasses but these are mentioned in the final chapters.

If you're, like me, still getting to grips with Ruby scripts and best practices this book is certainly worth reading to further your knowledge.


Rails

I've finally managed to get a Rails application working as a sub-domain on Slicehost. Capistrano and Deprec had set up everything fine, it was just that the DNS record needed adding.

Why didn’t I think of that?

  • Posted on Monday, 21 January 2008
  • Tagged with rails

Well, that didn't take long...

Amazon Web ServicesAmazon Web Services

In my iPhoto application I now have over 6,000 photos. Some I've taken with my Canon digital camera, but the majority I've scanned from negatives and added to iPhoto. With over 120 rolls of 36 exposure film to scan that little task took quite a while. But that was back in 2004.

My backup drive is a LaCie firewire drive that’s partitioned. One section is for a full iMac backup using SuperDuper!, the other, at the moment just contains a Time Machine backup. Just as a little aside, I was thinking of getting a Drobo and having loads of backups across lots of discs, but I've since gone off the idea.

So, the worry has been “What if my Mac and backup drive are destroyed by fire, power surge or are stolen?” I don’t have an offsite backup. I did think of just burning the photos to a couple of DVDs and putting the discs either in the garage or in my Dad’s safe, but that isn’t exactly ‘hi-tech’ for this day and age.

Reading around the internet I decided to try Amazon S3 (that’s Simple Storage Service) a part of Amazon Web Services. You are basically charged a per GB fee for storage per month, per GB transfer in and out in a month and for PUT, LIST and GET requests. It sounds more complicated than it is but at the moment my bill for the month is running at $1.73. Which with the dollar/pound exchange rate is very little indeed. That is after uploading nearly 11 GB of photos. The actual transfer in fee took the most of the total at $1.08.

To get my photo folder to S3 I used a set of Ruby based programs called S3Sync. I have been using rsync to download backups from my web-server, so I knew what to expect. After setting up a web services account with Amazon I added S3 to my set of connections in Transmit. It was this I used to create my first ‘buckets’ (a folder by any other name) on S3. This was fine, copying files and folders just like normal FTP. The only snag being that Transmit won’t, at the moment, let you delete any buckets that you've created. It just doesn’t happen. It even struggles deleting folders. I sent Panic an email and haven’t heard back, so I presume they know about it and are working on a fix for the next release. The only way to delete buckets, that I've found, is to install the S3 Organizer for Firefox, this works like a charm.

The majority of the tinkering took place last Thursday. Since then my iMac has been awake, during the day at least, and securely transferring photos to S3. It’s worked so well that I've set-up another bucket to take backups from my web-server directly to S3. I used to use the rsync command that I mentioned to download them to my iMac but from now on I don’t think I’ll bother.

So far the whole Amazon Web Services and S3 experience has been quite enjoyable. I just have to think of other uses for it.


Redesign

RedesignRedesign

Yes, I felt that a little redesign was in order.

I wrote a little Ruby script the other weekend to scrape my Digg RSS feed so that recently Dugg links could be listed on my blog. All it does is read in the XML, cut-out the titles and links and writes them out to a dugg.php file as list items. The file is then included in the sidebar. This is done, more or less, every hour for the hours in the day that I'm awake and could be Digging. All done on the web-server with a cron job. Of course Digg have now released an API which I will no doubt tinker with at some time. For the moment this way works fine.

This is the first time that I've written the stylesheet from scratch. The last one was based on Kubrick, the Wordpress default and so had lots of elements that I didn’t need or use.

A sidebar has been added which either has a double or single column based on the content. That was to make it easier to navigate without scrolling down to the links in the footer.

Each theme is still generated by a little Ruby program that I wrote. The switching is done with a change to the Wordpress stylesheet selector which switches the theme based on the current week.

  • Posted on Tuesday, 24 April 2007
  • Tagged with web, ruby, rails

Colour Shade

I wanted to be able to generate the shades of a particular colour.

This site has many themes with one main colour for the links and lines. But I wanted to be able to input the hex colour, that I had picked from the banner photo, and find a lighter shade for the menu section at the bottom.

Eric Meyer has written a Color Blender and I thought that I could do something similar using Ruby.

The program just takes the colour in hex (e.g. #ff0000 or even #f00), the shade number that you want and a number for the scale. Positive shade numbers make the colour lighter, negative numbers darker. Scale tops out at 100 and defaults to 10.

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
def colour_shade(colour, shade, scale=10)
  # default the scale to 100 if it is greater...
  scale = 100 if scale > 100

  # if the shade is out of the range of scale then reset shade to scale...
  if shade > 0
    shade = scale if shade > scale
  else
    shade = scale * -1 if shade < scale * -1
  end

  colour = "##{colour[1,1]*2}#{colour[2,1]*2}#{colour[3,1]*2}" if colour.length == 4

  # Convert the colours to decimal...
  colour_split = [(eval "0x#{colour[1,2]}"), (eval "0x#{colour[3,2]}"), (eval "0x#{colour[5,2]}")]

  # Calculate the shade...
  new_colour = "#"
  colour_split.each do |c|
    case
    when shade <  0: colour_shade = (c - ((c / scale) * shade.abs))
    when shade == 0: colour_shade = (c)
    when shade >  0: colour_shade = (c + (((255 - c) / scale) * shade))
    end
    new_colour << sprintf("0%x", colour_shade.to_i).slice(-2..-1).upcase
  end
  new_colour
end

Hover the mouse over the bars below to see what parameters were used to create the shades.

                     

                     

                     

Download the source code.

  • Posted on Sunday, 23 July 2006
  • Tagged with ruby, rails

4 more posts tagged with 'rails'…