Firefox 3 - With Colour Profiling Support!

June 18th, 2008

a tear in the fabric
a tear in the fabric, originally uploaded by chuck.bergeron

Just wanted to let you in a little (big) secret. Firefox 3 is out! It’s effin’ insanely good, I can’t even believe it. http://www.mozilla.com/en-US/firefox/

To get the full colour profile support, after downloading and installing open up a tab and instead of typing in http://whatever, type in about:config and press enter. It’ll warn you that you can screw things up, but just ignore the warning and continue on. Here’s where you can configure EVERYTHING about the browser. In the “filter” bar near the top, type in gfx and double-click the gfx.color_management.enabled option so that it’s value is set to true. Restart Firefox. Now your photos and everyone elses will look the way they should (no more desaturation on Flickr!) – wooo!

0 comments »

Upgrading to Capistrano 2.0

February 20th, 2008

Jesus, scary.

This past week I finally took the time to update my deploy recipe to the new Capistrano 2.0 format. It’s amazing how DRY the new namespaces feature is. I was able to take all of my custom tasks used for our Apis Networks shared hosting packages and separate them into their own plugin. This way, I’m no longer clobbering the default Capistrano deployment strategy.

It’s as easy as creating a two folders in your vendor/plugins directory. One for the name of the plugin, and one dubbed ‘recipes’. Here’s a typical directory tree:

1
2
3
4
5
-- rails_app
 -- vendor
  -- plugins
   -- your_cap_plugin
    -- recipes

Then, create a file in the recipes directory using any filename you like. Capistrano 2.0 will automatically load any tasks inside this file. Begin naming your deployment recipe inside it’s own namespace, like so:

recipes/tasks.rb

1
2
3
4
5
6
7
8
9
10
namespace :my_tasks do
  namespace :deploy do
    desc "Restart the FCGI ruby process"
    task :restart, :roles => :app do
      puts "Restarting the ruby processes..."
      # Ignore this confusing unix syntax, it's just for examples sake
      run "ps lx | grep ruby | grep -v grep | awk '{print $3}' | xargs --no-run-if-empty kill -9"
    end
  end
end

To hook your custom tasks into your deployment strategy, add before and after filters to your config/deploy.rb.

config/deploy.rb

1
2
3
4
5
6
7
8
9
10
namespace :deploy do
  # After restarting the ruby process, run the default cleanup task
  # and run my custom 'post_live' task
  after "deploy:restart", "deploy:cleanup", "my_tasks:deploy:post_live"

  desc "This overrides the default Capistrano deploy:restart task"
  task :restart, :roles => :app do
    my_tasks.deploy.restart
  end  
end

Re-usable plugin code, fun for every project!

Series: Plug-in arsenal - Paginating Find

February 15th, 2008

Books and recordsets!

Oh, pagination. How you have been tormented over the years in the Rails community. For those of you who have no idea what the devil pagination is, run a search on Google and take a look at near the bottom of the page – You should see “previous” and “next” links, alongside numbers of pages with which to jump to. That’s pagination!

I believe the majority of current opinion on paginating through records is to avoid using the Rails 1.0 built-in Pagination class. In Rails 2.0, it’s been removed and requires the install of an additional plug-in to receive the previous functionality. Cue Paginating Find, a plug-in written by Alex Wolfe of Carboard Rocket. I first learned of Paginating Find via Ilya Grigorik’s blog, as he had written some Helpers & View Partials to support it. Let’s jump in, shall we?

You can install Paginating Find here:
1
ruby script/plugin install http://svn.cardboardrocket.com/paginating_find

Paginating Find overrides the default ActiveRecord::find method, and allows a new set of options dubbed :page to accompany the familiar :conditions, :order, etc. We’ll use a Bulletin model for our example:

bulletin.rb (Model)

1
2
3
4
5
6
7
def self.find_all_using_pagination( options = {} )
  return self.find( :all,
    :page => { 
      :size => options[:number_of_records],
      :current => options[:current_page]
    } )
end

These options are typically provided by GET variables passed through the URL string to the controller. The new :page option requirs two vars, :size & :current. Use :size to dictate how many Bulletin’s should be pulled from the database per page, and :current to state which page we’re currently viewing. For example, if :current is set to 2, and :size is at 10, we would receive Bulletin’s 11-21.

The best part about Paginating Find is that it works transparently. If you don’t provide the :page option in the find() call, Rails will enact a regular find() call and ignore the fact that Paginating Find is even installed.

Further readings:

A Variation On Rails' Verbose Time Helper

February 5th, 2008

Oh tax season. Does anyone else find that January is the busiest month of the year?

A client of ours recently wanted a custom version of the built-in Rails helper distance_of_time_in_words. Basically, they were looking for a countdown that would dynamically let the customers know how much time they had left to order.

For those unfamiliar with distance_of_time_in_words, you provide it with Date & Time objects and it will state the duration between them in a more human readable format. For instance:

index.html.erb (View)

1
2
3
4
<%= distance_of_time_in_words( Time.now, 45.days.from_now ) %>
  # => about 1 month
<%= distance_of_time_in_words( Time.mktime( 2008, 02, 05 ), Time.mktime( 2008, 03, 29 ) ) %>
  # => about 1 month

This default behavior is great for informal purposes, such as how long it’s been since a blog article was posted or a comment made. However, I’ve come up with something a little more accurate:

1
2
3
4
<%= distance_of_time_in_words( Time.now, 45.days.from_now ) %> 
  # => 1 month, 14 days
<%= distance_of_time_in_words( Time.mktime( 2008, 02, 05 ), Time.mktime( 2008, 03, 29 ) ) %>
  # => 1 month, 22 days

application_helper.rb (Helper)

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
def distance_of_time_in_words( from_time, to_time = 0, include_seconds = true )
  from_time = from_time.to_time if from_time.respond_to?(:to_time)
  to_time = to_time.to_time if to_time.respond_to?(:to_time)
  distance_in_minutes = (((to_time - from_time).abs)/60).round
  distance_in_seconds = ((to_time - from_time).abs).round

  case distance_in_minutes
    when 0..1
    case distance_in_seconds
      when 0..59 then "#{pluralize( distance_in_seconds, 'second' )}"
      else             "1 minute"
    end

    when 2..59           then "#{distance_in_minutes} minutes"
    when 60              then "1 hour"
    when 61..1439        then
      hours, minutes = (distance_in_minutes.to_f / 60.0), (distance_in_minutes.to_f % 60.0)
      "#{pluralize( hours.floor, 'hour' )}, #{pluralize( minutes.floor, 'minutes' )}"      
    when 1440..1500      then "1 day"
    when 1501..2879      then "1 day, #{pluralize( (distance_in_minutes.to_f / 60 - 24).floor, 'hour' )}"
    when 2880..43199     then "#{(distance_in_minutes / 1440).round} days"
    when 43200..44641    then "1 month"
    when 44641..86399    then "1 month, #{pluralize( ( distance_in_minutes / 1440 - 30 ).floor, 'day' )}"
    when 86400..525599   then "over #{(distance_in_minutes / 43200).floor} months"
    else                      "over #{pluralize( (distance_in_minutes / 525600).round, 'years' ) }"
  end
end
Alternatively, we could use the method alias time_ago_in_words to skip the need for a first argument, and assume we’re comparing the current time with the provided distant time:
1
2
<%= time_ago_in_words( Time.mktime( 2008, 03, 29 ) ) %>
 #=> 1 month, 22 days (assuming current time is February 5th, 2008)

Welcome to 10.5! Migrating Your Tiger MySQL Databases to Leopard

December 28th, 2007

After quite a bit of deliberation, I’ve decided to move up from Tiger to Leopard. Thankfully, the path to Rails w/ MySQL has been much easier than it ever was on Tiger.

So far, my greatest obstacle has been installing MySQL and bringing my old databases over from my backup. The gracious folks over at Hivelogic have created a brilliant, line-by-line tutorial for building MySQL on Leopard.

After getting MySQL up and running successfully, I completely overlooked the fact that my databases would be wiped clean. I realized the easiest thing to do would be to copy the databases from my Tiger backup.

Note: Both of my MySQL installs are Version 5, so I crossed my fingers hoping they’d be compatible and so far there’s been no problems.

Step 1. Make sure to turn off your current Leopard MySQL install. The command for this in the tutorial is: sudo launchctl unload -w /Library/LaunchDaemons/com.mysql.mysqld.plist which sends the unload command to your plist file.

Step 2. Locate the “data” or “var” folder in your MySQL backup directory. For instance, mine was in /usr/local/mysql on my Tiger install.

Step 3. sudo cp -rf /Volumes/Backup/usr/local/mysql/data /usr/local/mysql Or substitute the paths for the proper source and destination. This will copy the database folder from your Tiger backup to your fresh Leopard MySQL install.

Step 4. sudo chown -R mysql /usr/local/mysql/data mysql Give ownership of the database directory to the mysql user.

Step 5. Start up the server and you should be good to go!

Happy Leopard’ing.

To Trick 'to_xml'

December 14th, 2007

XML Knowledge!

Recently, I’ve been sprinkling more and more XML into my projects. There’s a terrific helper method in Rails dubbed to_xml, which you can run over a collection of records.

At first, I had trouble using this because I was limited to outputting every typical AR attribute for the given model. (ie. I’d receive , , , etc. XML tags) After a bit of digging I found some options for to_xml which provides you with control over which attributes it XML’izes.

Here they are in action:

xml_controller.rhtml (Controller)

1
2
3
4
5
6
7
8
9
def compile_slides
  @slides = Slide.find( :all )
  
  # The :only call is necessary to omit all of the typical attributes
  render( :xml => @slides.to_xml(
    :only => [],
    :methods => [ :name, :cover_photo_url, :xml_url ]
  ) )
end

The :only option is overriding the to_xml’s default behaviour of spitting out every attribute, while :methods is stating which custom methods for the AR Model I want to include. For instance, instances of Slide repond to a method named ‘xml_url’:

slide.rb (Model)

1
2
3
4
5
6
7
def xml_url
  return "" if self.url.blank?
  return "http://#{self.url}" unless self.url[/http\:\/\//]
  return self.url
end

...

This will give us something like:

slides.xml (XML)

1
2
3
4
5
<slide>
  <xml-link>
    /articles/1-how-to-search-google
  </xml-link>
</slide>

Flexible!

Weak Apple Keyboards

November 27th, 2007

Today, my gal mentioned that for the third time in a year, something was amiss with her Macbook keyboard. This time it’s starting to crack a bit, which will only get worse as we all know. The first time the “V” key didn’t work at all, and the second the spacebar wasn’t registering properly on one side. Of course, all she has to do is take it to the Mac store on campus and they’ll fix it up for her under warranty at no cost, but it’s more of an annoyance than anything.

Don’t get me wrong, I love Apple & I’ve had much more luck with my Macbook. Still, I feel the need to dedicate this video to Apple and their shoddy laptop keyboards:

Rails hosting

November 22nd, 2007

My buddy just sent me a link to a hosting company I haven’t seen before: Site5. I’m curious as to how their customer support is, and how much control you get over your hosting package. (e.g. SSH? Multiple domains? etc.)

We at Carbon Media have always trusted our sites to Apis Networks, which we’ve had nothing but exceptional customer service from. Plus, they were more than accommodating when starting off with Ruby on Rails and helping us get our applications up and running.

However, Site5 does support Rails. If anybody has experience with this company, please leave a comment or send an email to let me know what you think of them! I may just have to start up a personal project to give them a test run…

Max / MSP

November 19th, 2007

I believe I’ll be skipping a post on Rails this week, as I’ve been sidetracked by a new toy:

Max / MSP in action

Max / MSP is a graphical programming language for audio, and it looks like it. The interface isn’t pretty, but it’s insides provide you with the powerful ability to create whatever your digital heart desires. This program has been around for over 15 years now, and has been used by quite a few artists I highly regard. The best part is, it’s extensible using C, Java and JavaScript! If you’re interested in both sound & programming, make sure to check it out. (wiki)

Series: My arsenal of plug-ins - Bundle-fu

November 12th, 2007

UPDATE: Looks like they’ve added functionality like this in Rails 2.0 using <%= stylesheet_link_tag( “main”, “forms”, “utilities”, { :cache => “frontend” } ) %>. Check out the latest release candidate w/ notes.

After writing about all of the nifty Firefox extensions I use on a daily basis, I had an idea to detail the Rails plug-ins and gems I’m in love with. This marks the beginning.

Bundle-fu fake logo

Tim Harper’s Bundle-fu plug-in was just the thing I was looking for while trying to cut down on the number of server requests per page. All you have to do is wrap both your stylesheets & javascripts in your layout file into separate code blocks, and bundle-fu will take care of the rest.

layout.rhtml

1
2
3
4
5
<% bundle( { :name => "styles" } ) do -%>
  <%= stylesheet_link_tag( "common", :media => "screen" ) %>
  <%= stylesheet_link_tag( "main",   :media => "screen" ) %>
  ... etc.
<% end -%>

This outputs a one-liner pointing to one lovely file all your css:

1
<link href="/stylesheets/cache/styles.css?20071111142032" media="screen" rel="Stylesheet" type="text/css" />

Here’s the install:

1
script/plugin install http://bundle-fu.googlecode.com/svn/tags/bundle_fu

Make sure to read the caveats page as there is a few (as always). I believe the largest is the fact that conditionally loaded stylesheets for Internet Explorer need to be outside of the code block.

Why I Won't Adopt Facebook's Pages Model

November 8th, 2007

Yesterday, Facebook released a new ‘feature’ on it’s social network dubbed ‘Pages’. After checking it out, and creating my own page I realized it was directly for marketing, probably to compete with Google AdWords and other such inventions.

Here’s the stitch, I already have a group on Facebook for my business with near 200 subscribed members. Do I really want to start over from scratch with a ‘Page’ that people can become a ‘fan’ of. No, I’m not in the least bit interested. In fact, I’m downright confused. What is the relevance of Groups at this point?

After reading a terrific article on TechCrunch what I already believed to be true was amplified, and I’m quickly losing interest in using Facebook as a method of marketing.

Good luck with your cash grab, FB!

In other news:

The US dollar is still on it’s greatest decline since the civil war, here’s a nice little extra that xe.com through up on their site:

Currency graph explicitly stating Canadian dollar worth more

Yup, they have to define what’s going on with a big question mark, possibly because a few fellow Canadians are actually stumped by the fact that our dollar is worth MORE than the Americano.

Keep elements in line with grids

November 5th, 2007

I just stumbled upon Allan Jardine’s Grid Bookmarklet, which quickly draws a grid in your browser on any page you’re viewing. It’s highly customizable as you go, so you can make sure your stylesheets are matching up with a proper grid template.

Grid Bookmarklet in action!

I could find myself using this one quite a bit.

Custom 404 Routes & Pages in Rails

November 3rd, 2007

Lately, I’ve been using a nice ‘catch-all’ trick in my routes.rb file to send users to a custom 404 page. It’s as simple as throwing this below the rest of your routes:

1
2
3
4
5
# If the user has typed an Invalid URL
map.connect "*path", :controller => "www", :action => "unrecognized"

# Make sure you don't have this default route in there:
# map.connect ':controller/:action/:id' # Comment or remove!

Now, if any invalid URLs are typed in, the app will respond by dishing up the action ‘unrecognized’ from the WwwController.

Here’s where the problem comes in. We recently redesigned a site using Rails, however I noticed that Google was continuing to index the old PHP version of the site just as it always had. Instead of removing the page from it’s index, it was displaying the content of my new custom 404 page. After some research, I realized the reason was my custom 404 page wasn’t a true 404, and was instead sending a 200 Successful HTTP response header instead. This turned out to be a quick fix, but I found it quite undocumented on the net:

1
2
3
4
5
class WwwController < ApplicationController
  def unrecognized
    render( :status => "404 Not Found" )
  end
end

Now our server will dish up the standard ‘404 Not Found’ HTTP response header. It’s just that easy.

Firefox Extensions I Use

October 23rd, 2007

Whenever somebody sits down at my laptop and uses it’s default browser, they’re generally curious as to what exactly is going on. It’s pretty cluttered (in an organized mess kinda way), and there’s all these crazy icon sets and toolbars everywhere. I’ve decided some clarification was in order, so here goes:

  • Joe Hewitt’s Firebug – The premier tool for anybody interested in advanced web development & design. When I found this one my job became 147% easier. Quickly jump right inside the DOM and see what’s going on. Edit stylesheets, live. View the network statistics of each page you request. Oh, did I mention it debugs JavaScript? The list goes on…
  • Yahoo’s YSlow – Can’t figure out why a page is taking forever to load? Convinced it isn’t SQL related? Enlist this helper to explain where the bottlenecks could be. (Requires Firebug)
  • Chris Pederick’s Web Developer – I had this one before Firebug, and I was impressed by it at the time. There’s two wonderful features I find handy in it these days: “Automatically Populate Form Fields” and “Disable JavaScript”.
  • Aaron Boodman’s Greasemonkey – Write custom JavaScript to be executed each time you hit a specified page. For instance, sick of filling in the username and password box on a site that won’t ‘remember’ you? Let Greasemonkey do it for you!
  • Alex Sirota’s ColorZilla – This glorious tool adds a tiny eyedropper (much like Photoshop’s) to the bottom left of your Firefox window. A great alternative to print-screen, open Photoshop, paste, select eyedropper tool, etc.
  • Kevin Freitas’ MeasureIt – A quick ruling tool which lets you draw boxes and see the width and height of any element, right in your browser.
    an example of the measureit add-on
  • Devon Jensen’s Download Statusbar – Firefox’s built-in file downloader is bulky and old-school. This pretty gem downloads files in a minimalist fashion at the bottom of your browser and gives you more functionality over how to handle downloads.
    an example of the download statusbar add-on
  • Zeniko’s Fission – A simple add-on which displays an animated loading progress bar to the URL (location) bar at the top. You even have a choice of colors. (woo!)
    an example of the fission add-on
  • Séparé – Purely cosmetic, truly organizational. Create lil’ orange tabs which separate one group of tabs from the next. (Warning: I have a feeling there may be some strange memory leak in this add-on, use at your own risk!)

And remember, if you find tons of use from any of these extensions then I urge you to donate! Most of them are developed by individuals who could probably use the help.

Think I’m missing one or two that you can’t live without? Let me know!

Overriding class methods for migrations, a follow-up

October 16th, 2007

I realized I left one important point out from my previous post. I’m sure a few of you may have already picked up on this as well. When you override the class in the migration, you can add in whatever methods you would like the migration to use. We’ll use the same example as before:

004_add_live_pages.rb

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
class AddLivePages < ActiveRecord::Migration
  
  # Say for instance the Page.rb model has 20 instance methods in it
  # that we don't want to have affect our migration, but there is
  # 1 method we want to use below
  class Page < ActiveRecord::Base
  
    # The method 'stripped_name' below is an extension
    # of the String class
    def set_permalink
      self.update_attribute( :permalink, "#{self.id}-#{self.stripped_name}" ) if self.permalink.blank?
    end
  
  end
  
  def self.up  
    page = Page.create(
      :name => "About",
      :body => "Write your about page content here.",
    )
    page.set_permalink
  end
  
  def self.down
  end
  
end

Ta da! Now we can use the ‘set_permalink’ instance method anywhere inside our migration