↓ Archives ↓

February 2012 Meetup Video

24 Ruby tips and tricks

Peter Cooper will share more tips in his book to be released later this year. Stay tune and don’t forget to leave your email address to get updates at http://rubyreloaded.com/trickshots/

Here are some of the tips in the video.

Generate random numbers within a given range

irb(main):019:0> rand(10..20)
=> 12
irb(main):020:0> rand(10...20) # works with exclusive range
=> 16

Dump your object using awesome_print

# Install the gem first
gem install awesome_print

irb(main):001:0> require 'ap'
=> true
irb(main):002:0> ap :a => 1, :b => 'greg', :c => [1,2,3]
{
    :a => 1,
    :b => "greg",
    :c => [
        [0] 1,
        [1] 2,
        [2] 3
    ]
}
=> {:a=>1, :b=>"greg", :c=>[1, 2, 3]}

Concatenating strings

irb(main):005:0> "abc" + "def"
=> "abcdef"
irb(main):006:0> "abc".concat("def")
=> "abcdef"
irb(main):007:0> x = "abc" "def"
=> "abcdef"

Include modules in a single line

class MyClass
  include Module1, Module2, Module3
  # However, the modules are included in reverse order. Confusing eh!
end

Instance variable interpolation

irb(main):008:0> @name = "greg"
=> "greg"
irb(main):009:0> "my name is #{@name}"
=> "my name is greg"
irb(main):010:0> "my name is #@name"
=> "my name is greg"

I still prefer the use curly braces.

Syntax checking

➜  ruby -c facu.rb 
facu.rb:12: syntax error, unexpected keyword_end, expecting $end

Zipping arrays

irb(main):027:0> names = %w(fred jess john)
=> ["fred", "jess", "john"]
irb(main):028:0> ages = [38, 47,91]
=> [38, 47, 91]
irb(main):029:0> locations = %w(spain france usa)
=> ["spain", "france", "usa"]
irb(main):030:0> names.zip(ages)
=> [["fred", 38], ["jess", 47], ["john", 91]]
irb(main):031:0> names.zip(ages, locations)
=> [["fred", 38, "spain"], ["jess", 47, "france"], ["john", 91, "usa"]]

Range into arrays

irb(main):034:0> (10..20).to_a  # what I used to do
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
irb(main):035:0> [*10..20]
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Using parameter as default value

irb(main):047:0> def method(a, b=a); "#{a} #{b}"; end
=> nil
irb(main):048:0> method 1
=> "1 1"
irb(main):049:0> method 1, 2
=> "1 2"

Put regex match in a variable

irb(main):058:0> s = "Greg Moreno"
=> "Greg Moreno"
irb(main):059:0> /(?<first>\w+) (?<second>\w+)/ =~ s
=> 0
irb(main):060:0> first
=> "Greg"
irb(main):061:0> second
=> "Moreno"


This post by Greg Moreno is from Greg Moreno.

RailsFTW, now twice as fast!

Rails FTW

My Game Jam post is waaay overdue but some stuff happened this week (impromptu upgrade, server migration) so I’ll only get around to post about it probably later today.

Anyway, this post is just about the new version up over at RailsFTW. This experimental build is based on TCS’s patched Ruby build which boasted a ~200% increase in performance.

See it for yourself:

This post by Bryan Bibat is from existence, refactored.

RailsFTW v0.10 released, now with Ruby 1.9.3 and Rails 3.2

Rails FTW

Still hung-over from Global Game Jam 2012 (mini-write-up later) when I went to the RailsInstaller site on a whim.

Noticed that it still isn’t using Rails 3.2. So I decided to update my own to be ahead again.

Hopefully this would be the last RailsFTW version (hoping Luis would be able to convince Wayne to include MySQL to RailsInstaller so I won’t need to this anymore LOL).

This post by Bryan Bibat is from existence, refactored.

January 2012 Meetup Videos

October Meetup Videos

Coding Screencasts

I’ve been doing some programming screencasts lately over my Youtube channel. They’re not really “screencasts” ala RailsCasts but more like informal streamed videos that you’d see in Justin.tv/Twitch.tv.

These screencasts were recorded in 720p so it’s a good idea to select a higher resolution then view the videos in full screen or the large player in order for you to read the code properly.

Here I code a hexagonal “game of life”-like cellular automata. Used Ruby, Gosu, and RSpec.

Walking through coding a simple Rails app. Bunch of technologies discussed like Twitter Bootstrap, Heroku, and git.

Going through Project Euler problems via brute force using Java.

This post by Bryan Bibat is from existence, refactored.

Learn how to setup a web server pt3: Installing MySQL and PHP apps (e.g. WordPress)

WordPress Installed

Here’s a quick update to this mini-tutorial. Previous parts can be found here and here.

Installing MySQL

Installing MySQL is so simple that I don’t need to hide it behind the cut. The one in the Ubuntu repositories work just fine:

$ sudo apt-get install mysql-server-5.1

Note that you will be asked to enter a root password somewhere in the installation.

To wrap up the installation run

$ sudo mysql_install_db

to initialize the installed server and

$ sudo mysql_secure_installation

to secure it.

In mysql_secure_installation, you’ll be asked for your root password and then you’ll asked if you want to change it. Just enter “n” since there’s no reason to change it this early. Then you’ll be asked if you want to do some things to secure the database which is, of course, what we want to do so just hit Enter for each question to choose the default answer (“Y”).


Installing WordPress

Now we go to making our Ubuntu + nginx + PHP + MySQL setup more useful by installing a web app. I choose WordPress for this tutorial because it’s both popular and easy to install.

Note that most PHP web apps out there have similar installation steps i.e. install prerequisites, setup database, download and extract files, and configure the app.

Installing prerequisites

We only need to install a few extra components for WordPress to work on our box:

$ sudo apt-get install php5-mysql php5-gd

php5-mysql is obviously required to allow PHP to connect to MySQL. php5-gd may be needed if you’re uploading images inside WordPress instead of using an external hosting.

At this point we are ready to follow the Installing WordPress guide.

Creating the database

I’ve switched around steps 1 and 2 because I prefer to do file-related tasks together instead of jumping from files to database to files again.

In setting up the database, we go with the client guide. Creating a new user isn’t part of that guide, though, so we’ll have to do that too.

Connect to the database using the root user:

$ mysql -u root -p

You will be prompted for the password before you can proceed. Once in, you can now proceed with doing what you need to do. The following lines will create a database named wp and a user named wp_user whose password is password_here.

mysql> CREATE DATABASE wp;

mysql> CREATE USER wp_user;

mysql> SET PASSWORD FOR wp_user = PASSWORD("password_here");

mysql> GRANT ALL PRIVILEGES ON wp.* TO "wp_user"@"localhost" IDENTIFIED BY "password_here";

mysql> FLUSH PRIVILEGES;

mysql> EXIT

Downloading WordPress and moving it around

Now it’s time to proceed with steps 1 and 3. Use wget to download and extract the latest version of WordPress:

$ wget http://wordpress.org/latest.tar.gz

$ tar -zxvf latest.tar.gz

We’ll then move the extracted folder wordpress/ to /var/www/ to centralize our web-app stuff.

$ sudo mv wordpress /var/www/

We also need to change the ownership for the folder:

$ sudo chown -R www-data:www-data /var/www/wordpress

Configuring it to work

First we need to add our database settings to wp-config.php:

$ cd /var/www/wordpress

/var/www/wordpress$ sudo mv wp-config-sample.php wp-config.php

/var/www/wordpress$ sudo vim wp-config.php

Change the settings as follows:

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wp');

/** MySQL database username */
define('DB_USER', 'wp_user');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

Now to edit our nginx settings.

$ sudo vim /etc/nginx/nginx.conf

We’ll be using a combination of suggested settings from both nginx and WordPress documents:

...
    server {
        listen       80;
        server_name *.mysite.dev;
        root /var/www/wordpress;

        if ($http_host != "mysite.dev") {
                rewrite ^ http://mysite.dev$request_uri permanent;
        }

        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
        }

        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location / {
                # This is cool because no php is touched for static content
                try_files $uri $uri/ /index.php;
        }

        location ~ \.php$ {
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass php;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                log_not_found off;
        }
    }
}

The main changes here are the update to the root (pointing it now to /var/www/wordpress) and the try_files approach of URL rewriting (which allows nginx to act like mod_rewrite without the use of .htaccess).

Wrapping up

Restart both PHP-FPM and nginx to apply the changes we made to both.

$ sudo /etc/init.d/php5-fpm restart

$ sudo /etc/init.d/nginx restart

Then go to http://mysite.dev to proceed with the “famous 5-minute install”.

WordPress Installer

WordPress Installed

You have now successfully installed WordPress.

This post by Bryan Bibat is from existence, refactored.

Learn how to setup a web server pt2: Installing Nginx and PHP

phpinfo()

Here’s the next part of my basic web server administration tutorial.

At the first part, we set up the virtual machine. Now we’ll be setting up the web server itself.

Set Static IP Address and fake Domain Name

Before we could proceed with installing our web server, let’s do a couple of things to make our server behave more like a “normal” server.

First is to set our server’s IP address to a static IP address. There are a bunch of ways to do this (e.g. change the router settings), but we’ll just go with changing our server’s settings

Running ifconfig and route will give us the current IP address and gateway.

ifconfig and route

In this case, the new IP address is 192.168.1.125 and the gateway is 192.168.1.5. We can now apply these settings to /etc/network/interfaces. Open the said file via:

$ sudo vim /etc/network/interfaces

(For this tutorial, I’ll be using vim as the default text editor. If you find vim too daunting, you can replace all instances of vim with nano)

It will look something like:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp

Now replace the last line with the following:

iface eth0 inet static
address [address here]
netmask 255.255.255.0
gateway [gateway here]

for example:

iface eth0 inet static
address 192.168.1.125
netmask 255.255.255.0
gateway 192.168.1.5

To make sure you got the static IP settings correctly, you can restart the server via

$ sudo shutdown -r now

or you could just simply restart the network interface:

$ sudo /etc/init.d/networking restart

Here we see the /etc/init.d folder where the init scripts (like networking) are placed. Aside from being executed automatically upon boot to start services, they can also be used to stop or restart the said services just like what we just did with networking. We will see more of /etc/init.d/ later in this tutorial.

Now that we’ve set the IP address as static, it’s time to set a fake domain name.

Normally, when you’ve got a server with a static IP address, you’d have to go and buy a domain name from a registrar like Namecheap and you’d go through the steps in linking that name with the IP address and waiting for the DNS propagation.

For this tutorial, we’re going to skip all that by faking it with the hosts file.

First let’s update the server’s /etc/hosts file to add our fake domain name “mysite.dev”:

sudo vim /etc/hosts

Add the line at the end:

192.168.1.125   mysite.dev

You can verify the new setting by using the ping command.

user@ubuntu:~$ ping -c 4 mysite.dev
PING mysite.dev (192.168.1.125) 56(84) bytes of data.
64 bytes from mysite.dev (192.168.1.125): icmp_seq=1 ttl=64 time=0.172 ms
64 bytes from mysite.dev (192.168.1.125): icmp_seq=2 ttl=64 time=2.38 ms
64 bytes from mysite.dev (192.168.1.125): icmp_seq=3 ttl=64 time=3.34 ms
64 bytes from mysite.dev (192.168.1.125): icmp_seq=4 ttl=64 time=1.59 ms

--- mysite.dev ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3016ms
rtt min/avg/max/mdev = 0.172/1.874/3.342/1.161 ms
user@ubuntu:~$

Now let’s apply the fake domain name mapping to the host Windows computer. Like in Linux, the hosts file in Windows requires admin privileges so we first need to run the text editor as Administrator in order to allow us to modify it.

Run as administrator

Right-click Notepad and select “Run as administrator”. Once open, you can now add the “192.168.1.125 mysite.dev” to the end of the C:\Windows\System32\drivers\etc\hosts file.

Now you could change the PuTTy settings to use “mysite.dev” instead of the actual IP address.

The actual installation of the web server below the cut.


Installing Nginx

It’s finally time to install the web server.

We won’t be using Apache, though. Instead, we’re going to go with its leaner and faster Russian counterpart nginx. We’re also going to build it from scratch (as opposed to getting it from a repository) to show you how its done in Linux machines.

Installing dependencies

We’ll need to install a few things before we could proceed with building nginx.

$ sudo apt-get install build-essential libssl-dev libpcre3-dev

build-essential contains the essential tools for compiling programs from source while the other two are libraries that nginx needs during compilation.

Building from source

~$ wget http://nginx.org/download/nginx-1.0.11.tar.gz

Using wget we download the latest stable source as of this writing. Yes, it’s a whopping 700 KB.

~$ tar zxvf nginx-1.0.11.tar.gz

We then unpack it using tar.

~$ cd nginx-1.0.11

~/nginx-1.0.11$ ./configure --sbin-path=/usr/local/sbin --with-http_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module

~/nginx-1.0.11$ make

~/nginx-1.0.11$ sudo make install

Now we finally perform the build/installation. This three-step configure-build-install scheme is pretty much how one builds any program in Linux from scratch.

This nginx build doesn’t come with an init script so we’ll have to download one off the net.

~/nginx-1.0.11$ cd ~

~$ wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx

~$ sudo mv nginx /etc/init.d/nginx

We still need to set a couple of things with the script:

$ sudo chmod +x /etc/init.d/nginx

$ sudo chown root:root /etc/init.d/nginx

The first command sets the script to executable and the other command gives the ownership of the script to root. Now we can run nginx:

$ sudo /etc/init.d/nginx start

You can now open http://mysite.dev to check if it’s installed properly.

nginx

Using Firebug or Chrome Developer tools will confirm the server’s really nginx 1.0.11.

nginx response headers

Tweaking nginx

Before we proceed with installing PHP, let’s apply some tweaks to nginx to make it more Apache-ish (lol) and then some.

$ sudo ln -s /usr/local/nginx/conf /etc/nginx

This creates a symbolic link in the /etc folder to match with the convention for configuration files.

$ sudo vim /etc/nginx/nginx.conf

Now we edit the configuration file like so:

user  www-data;
worker_processes  1;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    gzip on;
    gzip_buffers 16 8k;
    gzip_disable "MSIE [1-6]\.";
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    error_log  /var/log/nginx/error.log  debug;

    sendfile        on;
    keepalive_timeout  3;
    index              index.html index.htm;

    server {
        listen       80;
        server_name *.mysite.dev;
        root /var/www;

        if ($http_host != "mysite.dev") {
                rewrite ^ http://mysite.dev$request_uri permanent;
        }

        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
        }

    }

}

A quick summary of the changes:

  • We changed the server’s user from “nobody” to the system user “www-data”, the default user for web servers.
  • We set the file where the PID for the server would be located. This will allow our init script to stop or restart the server.
  • We enabled gzip for supported browsers to dramatically reduce the bandwidth usage.
  • We set the log to match Apache’s format.
  • We defined a handler for the *.mysite.dev domain, defining its root to be the same as Apache’s (/var/www)

Now to wrap things up:

$ sudo cp -r /usr/local/nginx/html /var/www

$ sudo chown -R www-data:www-data /var/www

We copy the html folder to /var/www and give it to www-data.

$ sudo mkdir /var/log/nginx

Just creating the log folder.

$ sudo /etc/init.d/nginx destroy

$ sudo /etc/init.d/nginx start

We force stop the server (as we haven’t defined the PID file when we started it) then start it normally.

Opening http://mysite.dev now shows us that the site is served as gzipped.

nginx response headers

Installing PHP-FPM

Unlike nginx, we won’t be building PHP from scratch. We will, however, not go with Apache’s mod_php/extension route and instead go the PHP-FPM route which, like nginx, is much leaner than the former.

Since PHP-FPM isn’t available in the official apt repositories of Ubuntu 10.04, we will have to use another repository. Nginx’s repositories may be a bit out of date (PHP v5.3.5 vs the current v5.3.8) but it should be enough for this tutorial.

$ sudo apt-get install python-software-properties

$ sudo add-apt-repository ppa:nginx/php5

$ sudo apt-get update

$ sudo apt-get install php5-fpm

The steps above will install PHP-FPM with fairly decent defaults. If you want to change some settings, you can modify the files at /etc/php5/fpm/ and restart the server via “sudo /etc/init.d/php-fpm restart“.

Now all we need to do is to tell nginx how to use PHP-FPM. Here’s our modified /etc/nginx/nginx.conf:

user  www-data;
worker_processes  1;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    gzip on;
    gzip_buffers 16 8k;
    gzip_disable "MSIE [1-6]\.";
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    error_log  /var/log/nginx/error.log  debug;

    sendfile        on;
    keepalive_timeout  3;
    index              index.php index.html index.htm;

    upstream php {
        server 127.0.0.1:9000;
    }

    server {
        listen       80;
        server_name *.mysite.dev;
        root /var/www;

        if ($http_host != "mysite.dev") {
                rewrite ^ http://mysite.dev$request_uri permanent;
        }

        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
        }

        location ~ \.php$ {
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass php;
        }
    }
}

The main changes between the original are:

  • Adding “index.php” before “index.html index.htm” to let the server prioritize the former over the latter.
  • The addition of the upstream php block that points to PHP-FPM.
  • The addition of the location handler for PHP files.

We also need to modify /etc/nginx/fastcgi_params, adding the following lines at the end of the file:

fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;

Once done we can now restart the server via sudo /etc/init.d/nginx restart.

To test PHP, create the phpinfo() index.php file:

$ sudo sh -c 'echo "<? phpinfo();" > /var/www/index.php'

Then open http://mysite.dev again:

phpinfo()

You have now installed nginx and PHP on your web server.

Benchmarking

You can use ApacheBench to see how well your site performs under load.

$ sudo apt-get install apache2-utils

Here’s 1000 requests with 100 concurrent users (10 requests each user) to our static HTML file:

user@ubuntu:~$ ab -n 1000 -c 100 http://mysite.dev/index.html
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking mysite.dev (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:        nginx/1.0.11
Server Hostname:        mysite.dev
Server Port:            80

Document Path:          /index.html
Document Length:        151 bytes

Concurrency Level:      100
Time taken for tests:   1.720 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      378290 bytes
HTML transferred:       157795 bytes
Requests per second:    581.31 [#/sec] (mean)
Time per request:       172.025 [ms] (mean)
Time per request:       1.720 [ms] (mean, across all concurrent requests)
Transfer rate:          214.75 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       27   79  15.7     84     102
Processing:    39   83  16.5     86     131
Waiting:       10   61  17.5     65      98
Total:        129  161  16.5    172     184

Percentage of the requests served within a certain time (ms)
  50%    172
  66%    173
  75%    173
  80%    173
  90%    178
  95%    182
  98%    183
  99%    183
 100%    184 (longest request)

Here’s the same test against our phpinfo() page:

user@ubuntu:~$ ab -n 1000 -c 100 http://mysite.dev/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking mysite.dev (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:        nginx/1.0.11
Server Hostname:        mysite.dev
Server Port:            80

Document Path:          /
Document Length:        42481 bytes

Concurrency Level:      100
Time taken for tests:   8.582 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      42649000 bytes
HTML transferred:       42481000 bytes
Requests per second:    116.52 [#/sec] (mean)
Time per request:       858.186 [ms] (mean)
Time per request:       8.582 [ms] (mean, across all concurrent requests)
Transfer rate:          4853.19 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    6  16.6      0      63
Processing:    66  810 126.3    861     875
Waiting:       59  808 127.0    858     873
Total:        125  816 113.2    861     875

Percentage of the requests served within a certain time (ms)
  50%    861
  66%    862
  75%    863
  80%    864
  90%    869
  95%    874
  98%    874
  99%    875
 100%    875 (longest request)

581 and 116 requests per second? Not bad for a “low end” server.

Proceed to part 3: Installing MySQL and WordPress

This post by Bryan Bibat is from existence, refactored.

RailsFTW v0.9 released, now with Rails 3.1

Rails FTW

Thanks to a Battlefield 3 Beta losing streak that I blame on my sucky internet connection, I’ve decided to update my hack-job of a standalone Windows installer for Rails.

Now there are two separate installers, a Ruby 1.8.7 + Rails 3.0.10 installer and a Ruby 1.9.2 + Rails 3.1.0. Here’s a table to give a quick comparison between these two installers with RailsInstaller thrown into the mix:

  RailsInstaller 2 RailsFTW (Rails 3.1) RailsFTW (Rails 3.0)
Ruby version 1.9.2-p290 1.8.7-p352
Rails version 3.1.0 3.0.10
File Size ~55MB ~20MB ~10MB
DB Adapter Gems sqlite3, pg, tiny_tds (MS SQL Server) sqlite3, mysql2
Additional Features git, DevKit -
Internet Connection Required? Yes No (Bundler will fail to connect to server but new apps will still work) No
Compiled by Some of the biggest names in the Ruby community Some random third world developer. LOL

This post by Bryan Bibat is from existence, refactored.