Monthly Archives: October 2007

Upcoming BarCamp and Montreal on Rails

BarCampNext BarCampMontreal is this weekend, November 3rd, I’ll be giving a short presentation on RefactorMyCode.com. I’ll also be giving away a free special and unique gift to celebrate RmC success and announcing a new secret feature, be there!

Montreal on Rails is next week, November 6th, I won’t be giving a presentation on anything, but lots of interesting people will.

There’s also a conference on castle system in Christianity, November 5th, in Madurai, India.

See you there!

Update: I can’t make it to India for the 5th, sorry!

2 Comments

Filed under conference, montreal, refactormycode

Moving to Rails 2.0

I know … it’s like exercising, you know you’ll be better afterwards but you don’t feel like going trough the pain right now. Updating a framework can be a pain, here’s a short list summarizing what I had to do to migrate RefactorMyCode from Rails 1.2.3 to 2.0 (Preview). I hope this makes it easier for you!

0. Pistonize it!

Instead of using the classic way of freezing Rails in you app tree (rake rails:freeze:edge TAG=rel_2-0-0_PR), I’d recommend using Piston:

piston import http://svn.rubyonrails.org/rails/tags/rel_2-0-0_PR/ vendor/rails

This way, you’ll be able to make changes to Rails code and keep them while updating your copy!

1. Update your stuff

Update configs, scripts and javascripts:

rake rails:update

2. Move your session config to environment.rb

Add this in your environment.rb and remove the session ... line in application.rb:

# Your secret key for verifying cookie session data integrity.
# If you change this key, all old sessions will become invalid!
config.action_controller.session = {
  :session_key => '_app_name_session_id',
  :secret      => 'your secret key'
}

To compute your secret key:

require 'digest/md5'
puts [now = Time.now, now.usec, rand(0), $$, 'you_app_name'].inject(Digest::MD5.new) { |md5, e| md5 << e.to_s }

3. Split environment.rb

Rails now recommend putting your specific config code in config/initializers. Move everything outside Rails::Initializer.run do |config| ... end into separate files. For starter, create config/initializers/inflections.rb and config/initializers/mime_types.rb and move what was in environment.rb. Split as much as you can in files with descriptive names.

4. Singleton resource, plural controller name

If you were using singleton resource: map.resouce :account, you’ll need to pluralize your controller name. In this case AccountsController. Not sure if it makes more sense, but follows the convention to pluralize controller names I guess…

5. Rename your views

Rails 2.0 brings a beautiful view naming convention:

[name].[content type].[template engine]

eg.: show.html.erb or create.js.rjs

Renaming manually can be pretty painful. Jamie created a Rake task for this.

6. Fix the plugins

Expects some plugins to break. In my case, asset_packager broke, but fixing it was simple: synching method signature for compute_public_path.

I’d recommend checking plugins compatibility before doing the jump. Read the doc. Or if you’re feeling adventurous, give it a try.

7. Add Request Forgery Protection

Cross-site request forgery can be hard to protect from. Not with Rails 2.0.

Add this to your application.rb

# See ActionController::RequestForgeryProtection for details
# If you're using the Cookie Session Store you can leave out the :secret
protect_from_forgery :secret => 'same_as_the_session_one'

And this to your config/environments/test.rb:

# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection    = false

Good luck!

Update: Paolo sent me an article he wrote for upgrading routes to 2.0 w/ a script, nice!

20 Comments

Filed under rails, tips, tutorial

Blogging from TextMate

It occurred to me that some people are still writing their blog post from WordPress, that is so last year. I also realized, while reading Hugh McGuire question, that TextMate is really powerful for blogging. I’ve been using it for quite some time now but didn’t realize until now all the tiny features I use while blogging. Here’s a short screencast of how I use TextMate to post to my blog.

TextMate blogger useful shortcuts

  • ^⌥⇧B – Switch to Blog bundle
  • ⇧⌘: – Spell check
  • ^⌥⌘ – Preview
  • ^⌘ – Publish
  • title[tab] – Snippet for post title
  • cat[tab] – Fetch the list of categories
  • ^⇧L – Turn highlighted text into a link (also fetch the page title!)
  • ^⇧⌘L – Search current text in Google and turn into a link
  • ⌘B – Make current text bold
  • ⌘I – Make current text italic
  • ^⌘T – Search through Bundle items (and shortcuts)
  • ^⇧⌥⇧⌘⌥X – Do absolutely nothing

Gary got another list of useful shortcuts in TextMate.

How do you write your blog posts ?

10 Comments

Filed under tips

Blitzweekend : Don’t do it!

This post is cross-posted on Blitzweekend’s blog

When Heri asked me to write a post on Blitzweekend’s blog to share some of my tips on building an app in one weekend I thought only of this one:

Don’t do it!

Truth is, if your manager and boss finds out you can do in 2 days what takes us 4 months at work, we’d all be screwed! So keep it quiet and pretend it was an old project you’ve been working on for a long time (months, even years if your boss is not that bright).

See the true story bellow:
Dilbert

If you’re still reading, maybe you don’t care about being labelled as a fast worker. Perhaps you just like creating new things so much, you can help yourself but build stuff again and again! But for most people the problem is: how to turn this into something other people can use. Not only you. Here are 3 tips I’d like to share with you on how to get that damn weekend project out the door, fast, without any pain (until you get labelled a fast worker) while having fun (for now! wait ’till you get labelled!).

1. Focus

Handle FindrKeep everything simple, as simple as it can get. Don’t try to solve all the problems in the world all at once. Find one problem, for example: greasy door handles, and solve that single problem: a web site for locating clean door handles in a specific building.
But hey, it would be cool to also share pictures of the greasy door handle with your friends! That’s when you start loosing focus. Choose only one idea and keep it simple and atomic. It should be impossible to split your project into smaller ones.

2. Remove, don’t add stuff

Here’s a quote I quote way to often:

Perfection is reached not when there’s nothing left to add, but when there’s nothing left to remove
– Antoine de St. Exupery

Don’t think of new features you could add to make it more cool. Think of which one are just too much or don’t add that much to your project. If you need to add features to make your project interesting it’s because your original idea sucks.

3 legs chicken, miam!It’s like a 3 legs chicken, if you pull on the features leg, you’re gonna need more resources and time. But if your time and resources are restricted, your only option is to cut off the features leg (who wants a 3 legs chicken anyway?).

If you think you’re going the wrong direction, start over. That’s why it’s important to put your code under source control from the beginning, revert is your friend when everything goes wrong!

3. Make it work already!

Don’t go big bang approach! Build sometime small, simple (even stupid) and release, rinse and repeat.
Most people don’t take the time to automate parts of their development because they think: it’s just a small project. Bullshit! Because it’s a small project, you’ll be making lots of small changes fast. So you wanna make sure you can deploy in one step, test in one step and restart, stop, cleanup, backup, eat, sleep in one step.

In the case of a web application, deployment can be time consuming if your not used to it. The Internet is full of guides on how to do it. Make sure you deploy a small version before your project gets too much dependencies. If something fails, it will be harder to find out which of the 10 libs you depend on is bogus rather the just making a bare-bone app work. I would also recommend automating your deployment with tools such as Capistrano, Vlad or Paste deployment.

Now that we’re all labelled as fast workers I think blitzweekend should be shrunk to 2 hours.

Have you built an app in 2 days yourself? Share some tips with us! (but don’t tell our bosses)

6 Comments

Filed under montreal, rails, tips

Gravatar caching plugin

Gravatar is slow.

You use Gravatar on your site.

Your site is slow.

We hate slow site.

Caching is fast.

Cache Gravatars on your site.

Your site is fast!

Get it!

script/plugin install http://code.macournoyer.com/svn/plugins/gravatar_cache

Or using piston:

piston import http://code.macournoyer.com/svn/plugins/gravatar_cache vendor/plugins/gravatar_cache

Place something like this in your Rakefile:

def gravatar_emails
  User.find(:all).collect(&:email) # Return the emails you wanna cache
end

Now put everything in place for showtime:

rake gravatar:setup

Cache it!

rake gravatar:cache

You might wanna run this in a cron job, here’s mine:

0 */3 * * * cd /var/www/refactormycode/current && /usr/local/bin/rake gravatar:cache RAILS_ENV=production

Caches it every 3 hours.

Now in your view (or helper):

image_tag Gravatar.new('an@email.com').url

Magic!

Page caching friendly

It should be optimized for really high traffic sites as there’s no hole in the caching process (there’s always a cached version and no chance that someone hits a semi-downloaded file). It is page caching friendly as the url to the image won’t change when it’s cached or not (always /images/gravatars/MD5_OR_YOUR_EMAIL.gif).

Warning

You might have guessed that using a different filename for each Gravatar won’t save you any bandwidth. Even if two images are the same, a different symlink will be created for each, causing a new request for each Gravatar (empty or not). I’d suggest not using this plugin if you’re concerned about bandwidth.

Hope this is helpful to anyone else then me. It was extracted from RefactorMyCode.com. Thanks to Daniel (code) and Matthew Hutchinson (code) for inspiration.

Digg it !

Update: I just found out that Gravatar was bought by Automattic, makers of Worpress. Here’s the news from their blog, TechCrunch, Mashable and Techmeme.

3 Comments

Filed under rails, refactormycode

Refactoring of the week

Since last week I pushed a whole lot of new features to RefactorMyCode:

  • Email notification when a new refactoring is posted
  • Edit your refactoring
  • More caching to make page loading über fast
  • Make popular page sort by week first, so old stuff doesn’t stay on top
  • Add an alternative OpenID in case your main one is down (set it in your account page)

One of the most popular code this week was posted by Frank Lamontagne from Ruby Fleebie and TimmyOnTime. He cross posted his last edition of the famous Rubyize this to RmC while using the trackback feature (allowing to send a trackback to your blog on each refactoring being made on the code). The idea of a Rubyize this is that he post a code that is poorly written on purpose and ask his readers to refactor it. Seeing the success of the 2 first editions was a trigger in my idea of building RmC. The results are always amazing in quality and diversity.

Here’s the code he posted:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def remove_insults(input)
   ctr = 0
   input.each do |word|
     word = word.downcase
     if word == "stupid" || word == "moron" || word == "dumbass" || word == "retard"
       i=0
       word.length.times do
          input[ctr][i,1] = "*"
          i+=1
       end
     end
     ctr += 1
   end

   puts input.join(" ").to_s
end

remove_insults "you truly are a moron sir!".split(" ")

Small_logo

Ugly no?

Not anymore, thanks to Jorel, Frank, Scott, Daniel and hungryblank who refactored it to:

1
2
3
4
5
def remove_insults(sentence)
  sentence.gsub(/stupid|moron|dumbass|retard/i) { |insult| '*' * insult.size }
end

puts remove_insults("you truly are a 'Stupid' moron, stupid sir!")

Shorter, faster, better! No this is not a Kanye West song, it’s beautiful code!

Leave a comment

Filed under refactormycode, ruby

3 simple tips to make your Rails app 100 times faster

After the initial meltdown of the RefactorMyCode server I had to find a solution to put it back online fast!

Here are 3 things I did that helped me put the app back online and made it amazingly fast serving more then 50 000 page load in a day, even if it was hosted on a shared hosting plan on DreamHost. Not the fastest provider but the cheapest and most supported for sure. I since then switched to SliceHost on an account graciously offered by StandoutJobs (that’s right, for my personal project, how cool is that?).

I know lots of people have wrote guides to make your web app faster, but I tried, with this one, to focus on the simplest, yet most effective, things you can do to dramatically speed up your app without loosing any of Rails and Ruby tasty sugar. I think even people with little experience with Rails and web deployment can follow this guide with no problem.

1. Pack that asset up

First tip is the easiest to put in place. Downloading your 3 stylesheets and 6 javascript files slows down page loading because the web browser has to open a new connection for each one. Plus some browser limits the number of files that can be downloaded from a same host at the same time.
The solution is to reduce the number of external resources your page depend on by merging all of them into one file. AssetPackager is great for doing this in your Rails app, plus it minifies your javascript for free, check out RefactorMyCode stylesheet and javascript file. All that by changing one line in your view layout!

Now to make it load even faster you want to move all your static files to another host (see why here). For example on RefactorMyCode, images, the stylesheet and javascript are loaded from assets.refactormycode.com.
With Rails, this is stupidly easy. In your config/environments/production.rb, set config.action_controller.asset_host to your assets host. Now all the image_tag, javascript_include_tag, etc will point to this host. On your DNS server, all you need to do is setup an alias (A record) pointing to the same IP as the main domain.

2. Remove unused stuff

Something to keep in mind while trying to improve performance is that, for each request, everything will be loaded, checked and executed. Authentication, session, database queries. Do you really need all this stuff on every request?

You can turn off session on specific actions with:

session :off, :only => :index

This boost performance like crazy. So it’s a great alternative to caching if you really need to go to the database but not to login the current user.

If you’re using RestfulAuthentication or ActsAsAuthenticated plugin, you can turn off loading the user form the cookie with:

skip_filter :login_from_cookie

which will save you one query.

Use fragment caching for partial views with heavy data from the db and skip your queries on the controller side with:

@users = User.find('all) unless read_fragment('unique_cache_key')

Also with queries, make sure you know how to use the :include option for eager loading of associations.

Post.find(:all, :include => :user)

will cut the number of queries in half.

3. Cache the whole page

This last tip is by far the most effective. Cache everything you can to reduce queries to the database, or even, requests to the dispatcher.
The best solution is caching the whole page into and HTML file so the web server serves the static file rather then sending the request to the dispatcher. Most web server are serving static files faster then Lance Armstrong on drugs. And can serve lots and lots of them, letting your dispatchers breath a bit between requests. Rails Envy as a great guide on how to set this up.

Now the hard part is caching the layout. To cache a full page, the page needs to be the same for every users, logged in or not. To do that, you have to remove all those <%= ... if logged_in? %> and show everything, at least in the HTML. You still can use javascript to show and hide links that are for logged in users. For example here’s a code sample from RefactorMyCode:

var CurrentUser = {
  loggedIn: false,
  author: false,
  admin: false,

  init: function() {
    this.loggedIn = Cookie.get('token') != null;
    this.admin    = Cookie.get('admin') != null;
  }
};

var Application = {
  init: function() {
    CurrentUser.init();
  },

  onBodyLoaded: function() {
    if (CurrentUser.loggedIn) {
      $$('.if_logged_in').invoke('show');
      $$('.unless_logged_in').invoke('hide');
    }
    if (CurrentUser.admin) {
      $$('.if_admin').invoke('show');
    }
  }
};

Another thing you wont be able to use anymore on your layout is <%= flash[:notice] %>. The flash changes on each request, not cacheable. The solution again is to transfert everything to the client with cookies and javascript. Cacheable Flash is a nice Rails plugin to do just this. Cool thing is, you don’t need to change anything on your controller. Just replace your previous flash ERB block with something like this:

<div id="error_div_id" class="flash flash_error"></div>
<div id="notice_div_id" class="flash flash_notice"></div>
<script type="text/javascript">
  Flash.transferFromCookies();
  Flash.writeDataTo('error', $('error_div_id'));
  Flash.writeDataTo('notice', $('notice_div_id'));
</script>

I hope this was helpful to you. Let me know if you got more tips or questions on how I’ve setup my server.

11 Comments

Filed under rails, tips, tutorial

Refactoring of the week

RefactorMyCode.com has now been (publicly) live for a week. It was amazing! Who would have though a simple site like this could attract more then 100 000 visits in a week ?

But what surprises me the most is how much the community is alive and healty. I haven’t had any spam really yet, well maybe 3-4. And 3 other posts from people saying “you suck”. But most of the time when people get upset in there, they apologies right after and people are really thankful when they get help, amazing! How different from forums and websites where people tell you to search or RTMF before thinking about helping you ? But RefactorMyCode is not for support anyway, it’s for challenging the mind ratter then fixing problems. Hackers like solving small well defined problems, I think that’s why the site is so successful.

To celebrate RmC first week anniversary I’d like to highlight one of the refactoring from this week.

Chris Lamothe submitted this one: Beautify JS Date to how recently the event occured.

This adds a .when() method to Date() object allowing you do things such as “Posted ” + someDate.when() + ” ago.” and get output such as “Posted 10 minutes ago.” I’ve refactored it twice but would like to see it even smaller.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/***
* Beautify date to how recent the event occurred compared to now.
* Some examples:  1 second, 4 hours, 10 days, 1 year.
*	Example:
*   var oneFiftyMin = new Date(new Date().getTime() - 60000 * 150);
*   alert(oneFiftyMin.when()); // will display "2 hours"
*
*  Handy for things like "Item posted " + someDate.when() + " ago."
*/
Date.prototype.when = function() {

	var diff = new Date().getTime() - this.getTime();
	var when; // our return value

	//TODO:  what if the time is in the future? 
	//if (diff < 0) throw new Error ("Date is in future, check timezone?";

	//one or more of these will be non-zero, but we only care about the biggest one (in scale of time)
  var secondsOld = Math.floor(diff / 1000);
  var minutesOld = Math.floor(diff / 60000);
  var hoursOld   = Math.floor(diff / 3600000);
  var daysOld    = Math.floor(diff / 86400000);
	var monthsOld  = Math.floor(diff / 2592000000);
	var yearsOld   = Math.floor(diff / (2592000000 * 12));  //your content is old!

	//determine which value is non-zero and assign appropriate text
  if (yearsOld > 0) {
		when = yearsOld + " year";
  }
  else if (monthsOld > 0) {
		when = monthsOld + " month";
  }
  else if (daysOld > 0) {
		when = daysOld + " day";
  }
  else if (hoursOld > 0) {
		when = hoursOld + " hour";
  }
  else if (minutesOld > 0) {
		when = minutesOld + " minute";
  }
  else {
		when = Math.round(diff /1000) + " second";
	}

	//add plural if necessary
	return (0 == when.indexOf("1 ")) ? when : when + "s";
} 

Small_logo

With the help of typefreak, Andre Steenveld and Tomasz Kołodziejski they finally end up with this code, that does exactly the same thing in less then one-third the line count.

1
2
3
4
5
6
7
8
9
10
11
12
Date.prototype.when = function(){
        var diff = (new Date() - this)/1e3,
        u = [ "second", "minute", "hour", "day", "weeks", "month", "year" ],
        s = [ 1, 60, 60, 24, 7, 4.333, 12, 1e9], // again fast hack - 1e9
        i=0;

        for(;;i++){
                if((diff/=s[i])<1){
                        return ~~(diff*=s[i])+' '+u[i-1]+(diff>1?'s':0);
                }
        }
}

Small_logo

What can you say ? WOW !

Thanks to all people who’ve taken the time to write me an email to report a bug, suggestion or simply to say thanks, it means a lot to me!

7 Comments

Filed under js, refactormycode

Montreal On Rails 3 tomorrow

Montreal on Rails 2Have you ever dreamed about being amongst the best developers in town ? Well, here’s your chance : Montreal on Rails is tomorrow! With 3 of the best Rails hacker in the world (of Montreal at least) presenting!

It’s in our StandoutOffice (suite 615). Register in the following 15 minutes and get the chance to sit on my chair, for FREE*!

* Conditions may apply. Participants will be required to have their hand clean, be freshly shaved and have a decent haircut.

4 Comments

Filed under conference, montreal, rails