Everyone loves git (unless you love mecurial), and svn is so passe, so it's time to hop on the bandwagon!

Step 1: Install Git. I use macports.

# sudo port install git-core +svn
Others may want to use one of these commands:

# sudo apt-get install git-core
# yum install git-core
# emerge -av git
# sudo pkg_add -i git-svn  
# sudo pkg_add -r git
Step 2: Check out your svn project with git. This may take a while, my project took about 20 minutes and it has 1300+ commits.

# git-svn clone https://svn.yourhost.name/projectname projectname.git
Step 3: Get any commits that may have been made to your subversion repo while you were exporting it.

# git-svn rebase
Now you've got a functional git clone of your subversion repo. git commands are very similar to svn commands. For example:

# git commit -a -m "This is a commit message"
# git help  (to learn about more commands)
If you want to commit the changes you have made to your git repo to your svn repo, it's quite easy:

# git-svn dcommit

Rails partials are are fragments of template code that can be inserted into a view. They can really simplify template code, by factoring out repeated code.

For example, I often put forms into a partial so that the form can be shared be create and edit views:

quizzes/new.html.haml
1
2
3
4
5

= error_messages_for :quiz
- form_for :quiz, @quiz, :url => quizzes_path, :html => {:method => :post} do |form|
  = render :partial => 'quizzes/form', :locals => {:form => form}
  = submit_tag 'Create'
quizzes/edit.html.haml
1
2
3
4
5

= error_messages_for :quiz
- form_for :quiz, @quiz, :url => quiz_path(@quiz), :html => {:method => :put} do |form|
  = render :partial => 'quizzes/form', :locals => {:form => form}
  = submit_tag 'Update'

Many (most) people put the render call directly in their templates. This is not a good idea! What if you want to change the template path, or conditionally render a different template in certain conditions? Now you've got to repeat yourself in both templates, and that's bad news.

A simple way to fix this is to *always* use a helper to render the partial. That way any changes can be made in one place, and it also a great place to store any messy conditional logic so that it doesn't clutter up your templates.

quizzes/new.html.haml
1
2
3
4
5

= error_messages_for :quiz
- form_for :quiz, @quiz, :url => quizzes_path, :html => {:method => :post} do |form|
  = quiz_form(form)
  = submit_tag 'Create'
quizzes/edit.html.haml
1
2
3
4
5

= error_messages_for :quiz
- form_for :quiz, @quiz, :url => quiz_path(@quiz), :html => {:method => :put} do |form|
  = quiz_form(form)
  = submit_tag 'Update'
quizzes_helper.rb
1
2
3
4

def quiz_form(form)
   render :partial => 'quizzes/form', :locals => {:form => form}
end

Now if I want to do something, like say render a different form depending on a user's preference, it's easy to do.

quizzes/new.html.haml
1
2
3
4
5

= error_messages_for :quiz
- form_for :quiz, @quiz, :url => quizzes_path, :html => {:method => :post} do |form|
  = quiz_form(form, current_user)
  = submit_tag 'Create'
quizzes_helper.rb
1
2
3
4
5
6
7
8

def quiz_form(form, user = nil)
   if(!user.nil? && user.wants_advanced_quizzes))
     render :partial => 'quizzes/advanced_form', :locals => {:form => form}
   else
     render :partial => 'quizzes/form', :locals => {:form => form}
   end
end

IE8 beta is out

March 5th, 2008

A lot of people were really optimistic when it was announced that IE 8 would render Acid2, something that Firefox2 can't even do (Firefox beta3 can however).

It was thought that Microsoft was finally catching up in terms of standards compliance with the other popular browsers. To bad that rendering Acid2 doesn't really mean that the browser is 'standards compliant'. It just means that it can render the subset of the standard that Acid2 tests. With the release of Acid3, it looks like Microsoft focused solely on rendering Acid2, not on the standards in general. IE8 scored a poor 17/100 on Acid3.

Webkit Acid3 result

On the opposite end of the spectrum, Apple's latest Webkit beta scored 86/100.

Webkit Acid3 result

Learnhub launches!

March 4th, 2008

The entire Savvica team has been busy since November building Learnhub, which we launched today at noon. We've had a great time building it, and have a ton of ideas for future features. Check it out!
Learnhub Screenshot

A gotcha

February 27th, 2008

Just got bitten by this. Observers are not called when deleting an object via a through collection.

An example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class Newsletter < ActiveRecord::Base
  has_many :subscribers
  has_many :users, :through => :subscribers
end

class SubscriberObserver <  ActiveRecord::Observer
  def after_destroy(subscriber)
    # do somethng
  end
end

# case 1
# deletes a subscriber object. after_destroy is not called
@newsletter.users.delete(user) 

# case 2
 # after_destroy is called.
subscriber = @newsletter.subscribers.find(:first, :conditions => ["user_id = ?", user.id])
subscriber.destroy unless subscriber.nil?  

In both cases a subscriber object is being destroyed, but the observer is being called only in the second scenario. I'll have to look into patching this when I get a chance ....

One thing I hate about Rails ...

February 26th, 2008

One thing I truly hate in Rails is ActionMailer. It sucks.

First off (admittedly a minor point), mailers are stored in app/models, even though they are basically a pseudo controllers, complete with view templates (stored in app/views). It makes no sense.

Secondly, ActionMailer does not have access to named routes or any view helpers. The 'rails way' would be to call the mailer from a controller, passing the URL as an argument which is just stupid in my opinion. Most of the time I send an email in an application it is due to a change in an model's state, not due to a specific controller interaction. A nice way of doing this through use of active record observers (which also don't have access to routes).

This means I generally end up hardcoding the URLs in the mailer. It wouldn't be a huge deal if my test coverage checks that the hardcoded url in the email body matches a generated one. But to do that you'll need to write integration tests rather than the default 'ActionMailer' tests that are auto generated. The whole mess frustrates me unlike anything else in Rails.

Merb seems to get it right with its Merb::MailController. Perhaps something similar could be added to Rails via a plugin?

Immutable Attribute Plugin

November 14th, 2007

A new Ruby on Rails validation plugin that allows you to mark model attributes as immutable. Rails surprisingly does not include a validation method to make a model attribute immutable. (That is, the attribute can not be changed after it is set the first time.) I created this validation plugin to help that. Check out my post on the Savvica blog.

Updates and such ...

November 3rd, 2007

I resigned my position with TSOT a few weeks ago, and have joined John and Malgosia at Savvica. We're going to be building some pretty cool stuff!

Last week Carsten and I were able to knock off a beta of Languify, which is a tool to help software developers to collect and manage language translations for software localization. It's pretty simple for now, but we've got a lot of cool ideas that we'll be implementing in the near future. Keep an eye on it!

Rails on OpenBSD

August 10th, 2007

It's extremely easy.
  1. Install your favorite database server. My favorite is Postgres.
    
    
    $ sudo pkg_add -i postgresql-server
  2. Install the ruby database bindings for your favorite database server.
    
    
    $ sudo pkg_add -i ruby-postgres
  3. Install rails.
    
    
    $ sudo pkg_add -i ruby-rails
That's it!. pkg_add is a great tool (much like apt on debian systems) that takes care of all of the package dependancies.

haml & sass

August 9th, 2007

haml is template languages for Ruby on Rails. It's a plugin that provides an alternative to Rails' native view templating library erb. sass is included with haml, and provides templating for css files. Through clever usage of whitespace, both remove much of the verbosity of html and css (<>, end tags ,etc) , providing a concise way of creating templates. For example, take this typical layout template:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title><%= controller.action_name %></title>
  <%= stylesheet_link_tag 'mycss' %>
</head>
<body>
  <p style="color: green">
    <%= flash[:notice] %>
  </p>
  <div id="header">
     <h1>Header</h1>
  </div>
  <div id="content">
    <%= yield  %>
  </div>
</body>
</html>
Here's the same thing in haml. Notice the usage of whitespace to delimit block the nesting of the code. Also, regular html can be mixed in as well.
1
2
3
4
5
6
7
8
9
10
11
12
13

!!!
%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"}
  %head
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    %title= controller.action_name
    = stylesheet_link_tag 'mycss'
  %body
    %p{:style => "color:green"}= flash[:notice]
    #header
      %h1 Header
    #content
      = yield
There are a few benefits to this:
  • the information density is greater, so more of the template is visible on screen.
  • less characters to type, so less chance to make a typo
  • nesting is clearly visible, and no more issues with missing end tags.
sass is similar to haml in that it uses whitespace for nesting, eliminating verbosity. In my next article, I'll explain the benefits and usage of Sass.

Facebook Garage - Part 6

August 7th, 2007

Demo: Carpool by: Rajat Suri

Rajat explains how he produced the idea of Carpool, and how Facebook was the perfect (only?) platform to build it. Facebook already has the users, and it connects people that already trust each other (at least on some level).

The app is pretty cool, it shows rides offered and needed, how many miles the user has travelled, and how many CO2 emissions have been avoided by carpooling. Rajat should talk to Zero Footprint about this :)

Demo: My Aquarium by Greg Thomson

This developer's applications have a total of 2.6 million users and 75,000 new users per day. (wow!)

Greg talked about profile updates, which apparently have a failure rate of 5%. He solved the problem by having a queue that runs all of the time, attempting requests until they succeed.

Facebook Garage - Part 5

August 7th, 2007

Updating the Facebook Profile. by Colin Smillie

Rules:
  • content rules
    • no iframes, or auto-running flash
  • display rules
    • consistent presentation and user experience
Caching
  • The profile page is cached, so your app must notify facebook in order to update the profile page.
  • See the fb:ref method for updates.
  • multiple handles are possible, so you could update many profiles at once (think of a horrorscope application, only 12 updates would need to be made for many users

Application Demo: "My Free Stuff", by: Ricardo Covo

Ricardo presents his application which was developed with MS tools (dotNet + SQL Server). He also uses iframes, which seems to be less common. Like Rails, dotNet has an API wrapper (several) for ease of use.

Ricardo found the facebook platform to be extremely easy to develop for, and the api wrappers provide seamless integration into your own platform of choice.

Facebook Garage - Part 4

August 7th, 2007

FQL: Overview by Craig Saila

Facebook API calls are just embedded FQL calls.

Advanatages:
  • common syntac for all methods
  • condense facebook queries
  • reduce response size
FQL is very similar to SQL. Sub selects are allowed, etc.

Ex: SELECT current_location FROM user WHERE uid = 324324. This will return an XML response.

There are about two dozen tables that can be queried. The users table is most often queried.

FQL contains some helper functions that help with queries. It's quite PHP like.

You can only query against "indexable" columns in your where statement. You need at least one in your query.

FQL is designed to be efficient, so no JOIN, ORDER BY, GROUP BY or LIMIT. Each FROM can only reference one table. You must also specify each field that you want the query to return ("SELECT *" is not allowed). Sorting of data, etc must be done on the application level.

Tips:
  • Use the developers tools (fql.query)
  • Read the API docs
  • Share what you learn on your blog or wiki

Facebook Garage - Part 3

August 7th, 2007

FBML (Facebook Markup Language) introduction by Sunil Boodram

FBML is used to tap into Fackbook elements to ease application creation. It's somewhat similar to HTML. Ex: <fb:gogle-analytics> will generate the proper html to add Google Analytics tracking into your app.

Many of the HTML tags work in FBML. Notable exceptions include <script> and <style>. You may use css in your app, but it will be altered in order for it to not break the look of facebook itself.

Facebook provides an FBML test console, which saves repeated uploads to your dev server when building an application.

Check the FBML documentation for existing tags, they make life much easier!

Jay Goldman explains the anatomy of a facebook application.

Applications go into the application directory
  • make it look pretty!
  • use good keywords, be descriptive
The about page:
  • This page can be really used to sell users on the app. Make it convincing!
Application left nav:
  • The icon and name are important so that the user remembers what it looks like so they can find it
Canvas
  • Where your application's app is displayed
  • Put compelling content on the canvas page, ex: information from your friends
Dashboard
  • should contains the user's data, rather than the data from their friends
Privacy settings
  • consider what will happen if the user turns any of them off
Infecting
  • profile action links
  • news feed
  • message attachments .. you can attach pretty much anything!
  • requests: you can only invite ten friends per day
The Facebook developer garage came to Toronto this evening, at MARS. It's a popular event as the main presentation room is packed, and a second room is setup with an audio/video feed. Both CBC radio and CityTV News have reporters covering the event.
  • Facebook has 15 billion page views/month
  • 2400+ applications, 100 million downloads
  • This is the 1st facebook dev garage in Canada to encourage more developers to write apps on facebook

Highlights from the first presentation:

Facebook platfom
  • Canada has 10% of all facebook developers
  • Toronto is one of the top ten cities for facebook developers
  • 33 million active users!
  • 150, 000 new users per day
  • 1,700 applications with more than 100 users
  • Facebook social graph
    • Identity
    • Information
    • Social Context
  • Ninja tricks
    • More integration points == better
    • News feed is still quite important
  • Profile integration
    • Feed shows installations and application actions (add a photo, etc)
    • Recent Interactions
    • Recently Added Content
    • Social Relevancy
    • Content for expression (not consumption)
    • Timestamps are important (when did it happen?)
    • Users want to show off
  • Canvas Page Engagement
    • Keep the captive audience
    • Use social comparisons
    • Increase engagement
    • Action buttons are good == big buttons that will generate events that go into the feed
  • Lesser used integration points
    • Message
    • Composer
    • Profile actions
    • Wall
    • Share
  • Mass distribution
    • at least 75% users have installed an app
  • Feed the mini-feed
    • Primary Actions
    • Temporal
    • Include friends
    • Increase Relvancy
    • Utilize Call-to_action buttons
  • Build Apps to promote core business
    • Cross-promote
    • Interactive Cross-promotion (ex: iLike)
  • New Opportunities Virtual currency
    • incentive based actions
    • self promotion
    • social promotion
    • ex: pet someone else's pet and earn money. excahnge money to give gifts to other user's pet
    • so basically give social capital == rewards for interacting with the site
    Ad Networks
    • apps allow ad network to advertise on your app's canvas space
    • high cpm's ($20)
  • APIs on top of the API
    • ex: post on SuperWall instead of Wall
  • Metrics to think about
    • the facebook effect (aka: the slashdot effect)
    • provides dramatic traffic growth to external sites
  • Virality metrics
    • Installed base
    • Outgoing impressions
    • Conversions
  • Engagement metrics
    • repeat sessions, etc

There are more articles about the presentations listed below:

IE and innerHTML stupidity

August 7th, 2007

In today's Ajaxy web, web developers find themselves dynamically displaying content more than ever. One issue that may bite you is the IE 6 implementation of innerHTML. For example:
1
2
3
4
5
6
7
8
9
10


new Ajax.Request(url, { 
                      method: 'post',
          onComplete: function(request)
          {   
              $('mydiv').update(request.responseText);
                                            // .... do more stuff, etc
          }
         });
In IE 6 you may find that the code is throwing an error on the update call (which in IE uses innerHTML). The problem is that the html returned by the Ajax call is not technically valid. It may contain <style> or <script> tags for example, or perhaps the target element is does not allow inner blocks (<p> for example). The worst part about it is that the error does not contain any sort of helpful error message to help you out. Also, the same code will likely work fine in other browsers such as Safari or Firefox. So if you happen to run into problems updating an element in IE, take a close look at the content that you're trying to insert. IE 6 is very stringent about what it allows.

TSOT is hiring!

June 12th, 2007

TSOT is looking for top notch Ruby on Rails developers here in Toronto. We just recently filmed a recruiting video with Standout Jobs, a Montreal based startup focused on recruiting. Check it out, and if you're a good fit then get in touch!

Railsconf 2007

May 21st, 2007

I have spent the past four days in Portland OR, attending Railsconf. This week included a couple of firsts for me:
  • It was the first tech conference that I've attended
  • My first trip to the west coast. Well, to be truthful, my first trip anywhere west of Sarnia! I need to travel more ....

Highlights

  • David Heinemeier Hansson's keynote on friday. Rails 2.0 won't be a revolution as much as an evolution, but it's shaping up to be another fantastic release
  • Jim Weirich's presentation "Spam I Have Known". Jim is an excellent speaker, and he explained the issues involved in eliminating wiki spam in an entertaining fashion.
  • The Open Mic sessions. They were a fair bit shorter than the ones given at Demo Camp (5 minutes rather than 15) which worked quite well. Statisfy.net was cool, if gimicky.
  • The Rails Way talk/Q & A with Jamis Buck and Michael Koziarski. They were a real life version of their fantastic blog, The Rails Way, and they also held a Q & A session, with questions posted via IRC. They pointed out the proper way to use 'map' in routing which prompted me to overhaul all my routes utilizing 'map.with_options'.
  • "Choose Your Battles and LetIt::REST" by Hampton Catlin and Jeff Hardy. Their idea of making controllers 'resourceful' looks REALLY promising. I can't wait until it's released
  • Dave Thomas's closing keynote. He challenged the Rails community to innovate, comparing the way that we deliver web applications now to the mainframes that served applications in the 1970's.

Lowlights

  • The presenter for "Rails Security: Theory and Practice" was a no show. Maybe he thought that his former roommate (who was in attendance) was going to try to shake him down for being a deadbeat ex-housemate