Take control of your guards
By default, guard runs all your stuff on start and after the tests you are working on passes. In smaller projects, this is okay because your test suite can run a little faster. However, when you accidentally pass all tests on a big project, you’ll be doing quite a bit of waiting before you get back into your TDD cycle.
You can imagine how all that waiting can add up. Here’s how you can set up rspec and cucumber guards such that they only run all when you tell them to:
guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do # ... guard 'cucumber', :all_on_start => false, :all_after_pass => false do
Using factory_girl definitions in console
In my Gemfile, I am using factory_girl like so:
gem 'factory_girl_rails', :require => false
This makes your development environment load a little faster, but also means that you don’t have access to your factories in your development console.
No worries, loading factories is actually pretty simple. In your console do this:
require 'factory_girl' FactoryGirl.find_definitions
Just create/build factories as you normally would.
Updating nginx with Passenger module
Installing Passenger with nginx was very painless as shown in my last post setting up a Rails stack on Ubuntu, but unfortunately, the current version of Passenger will install nginx 1.0.0. I needed to be able to set environment variables for the continuous integration server I was building, which required a later version with the latest being 1.0.4.
The first thing you want to do is set your system up to install nginx:
$ sudo apt-get install libpcre3 libpcre3-dev $ wget http://nginx.org/download/nginx-1.0.4.tar.gz $ tar zxf nginx-1.0.4.tar.gz
Although passenger helps us install the older version of nginx by default, we can choose the more advanced option of installing the one we just downloaded by first entering this command:
$ rvmsudo passenger-install-nginx-module
When prompted, choose to select your own version of nginx, enter the source location and install it to /usr/local/nginx. If you had followed my previous blog post, you may have noticed that Passenger installs nginx to /opt/nginx by default, so you may want to delete that whole folder off later.
At the end of the installation, you will be asked to copy and paste these two lines into your config file:
passenger_root /home/app_user/.rvm/gems/ree-1.8.7-2011.03/gems/passenger-3.0.7; passenger_ruby /home/app_user/.rvm/wrappers/ree-1.8.7-2011.03/ruby;
Note that the second line is really important for some reason especially if you are using RVM. I had thought to fill that in myself, but without the wrapper it did not work. Also, don’t copy and paste these lines; you probably have a different version of Ruby installed, so use the ones suggested in the install.
Setting up Ubuntu for Rails 3 on Passenger & nginx From Scratch
I had the itch to set up a continuous integration server but didn’t want to set up a physical box for it because I was too lazy, and also because I don’t have such hard lying around. I guess it was more of the latter.
With that, I did a rigorous 10-minute review of hosting providers and settled on Rackspace because I didn’t need a lot of power for this thing and Rackspace was pretty much the only cloud hosting provider that allows you to provision a really small slice for about $10 a month.
About an hour later, I was set up with a clean Ubuntu 10.10 install. True to the title of this post, this is where we start.
Step 1: Don’t log in as root
So we should all pretty much know why logging in as root is not a good idea, so let’s just get this out of the way.
adduser app_user
The adduser command creates a user account with some defaults. Next, edit your /etc/sudoers file by adding this line:
$ app_user ALL=(ALL) ALL
Disconnect from the server and reconnect back as your new account. Now, change your SSH settings to prevent users from logging in as root
$ vi /etc/ssh/sshd_config
Search for theline where PermitRootLogin is commented out or set to yes and change it to:
PermitRootLogin no
For the changes to take effect, simply do this:
$ /etc/init.d/ssh restart
No rocket science here.
Step 2: Set up the system for Ruby with RVM
RVM is pretty neat and you ought to just install it just because. But first, we’re going to have to update the system itself; get the latest packages by performing these three commands:
$ apt-get update $ apt-get install build-essential $ apt-get install ruby ri rdoc irb ruby-dev libruby libreadline-ruby libopenssl-ruby libssl-dev libreadline5-dev git-core zlib1g zlib1g-dev libcurl4-openssl-dev libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev libxml2 libxml2-dev libxslt1-dev sqlite3 libsqlite3-dev libpcre3 libpcre3-dev
Depending on your needs, some of these packages could be omitted, but I tried my best not to add anything that wasn’t really necessary when compiling this list.
We’re going to use the official installation instructions because it just works.
$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm) $ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile $ source .bash_profile
This should set up your system with RVM, which makes us ready to install the rubies we want. I’m going to be installing Ruby Enterprise Edition, which is also what I use when I deploy apps to Heroku.
$ rvm get latest $ rvm reload $ rvm install ree-1.8.7 $ rvm use ree-1.8.7
Running these commands will probably take some time, so check back in a minute. If you want to use REE as the default ruby, you can do this:
rvm --default use ree-1.8.7
Step 3: Installing Passenger & nginx
Now we come to the really fun part. Okay, I’m kidding, setting up server software is not really that fun (bad experience for me). Lucky for us, we’re gonna be using nginx, which isn’t that bad.
Installing such software usually requires super powers, the kind that you get with sudo. However, due to the way RVM works, we cannot use sudo directly with our Ruby commands. Fortunately, RVM provides us with an alternative command:
$ rvmsudo gem install passenger $ rvmsudo passenger-install-nginx-module
Be sure to select option 1 to let Passenger and install and configure nginx for you. The config file can be found in /opt/nginx/confg/nginx.conf
To make it easier to start/stop nginx, we will be creating an init script (courtesy of Hackido) like so:
$ cd /etc/init.d/ $ sudo wget http://vince71.googlepages.com/nginx $ sudo chmod +x /etc/init.d/nginx
Once you are done, you should be able to perform these commands on nginx:
$ sudo /etc/init.d/nginx start $ sudo /etc/init.d/nginx stop $ sudo /etc/init.d/nginx restart
or
$ sudo service nginx start $ sudo service nginx stop $ sudo service nginx restart
Remember to use sudo; without it, the script runs as if it were successful, but does not start/stop the server at all.
Lastly, we will want nginx to start each time the server boots and that’s what the init script is going to help us with. All you have to do is run this:
sudo /usr/sbin/update-rc.d -f nginx defaults
I’m not exactly sure why, but my installation of nginx did not come with the sites-available and sites-enabled folders. With these two folders, it becomes easy to set up multiple configuration files for your different sites. Simply put the config files in the sites-available folder and symlink to it from sites-enabled to enable the site. And of course, remove the symlink to disable the site.
$ cd /opt/nginx $ mkdir sites-available sites-enabled
To include the configuration files in the sites-enabled folder, add this line to your config file:
include /opt/nginx/sites-enabled/*;
Creating the site-specific config files are a straight forward matter and I will go into that in a later blog post when I will be setting up CI Joe.
Configuring Redis on Maverick Meerkat
If you followed my earlier blog post on installing Redis (I’ve updated it a bit), you should already have Redis on the system.
To set Redis up in a production-like environment, we’re going to create an init script, which I’ve modified from Dan’s post. With this, we will also be setting it up to run on boot.
$ cd /etc/init.d
$ sudo wget https://raw.github.com/gist/1066656/5e58c1154b3f090b225970c68fb3cea817522e62/redis-server
$ sudo chmod +x redis-server
$ sudo update-rc.d redis-server defaults
You can continue following Dan’s post, but I’m just going to reproduce the commands here he used to set up a user for running Redis:
$ sudo useradd redis
$ sudo mkdir -p /var/lib/redis
$ sudo mkdir -p /var/log/redis
$ sudo chown redis.redis /var/lib/redis
$ sudo chown redis.redis /var/log/redis
Now, you can perform commands on Redis like this:
$ sudo /etc/init.d/redis-server start
$ sudo /etc/init.d/redis-server stop
$ sudo /etc/init.d/redis-server restart
To really configure Redis for primetime, you will have to edit your config file to suit a production environment.
Note: one issue is that running it this way is that it starts Redis in the foreground. I’m still quite a Linux noob so what I did was restart the server. Since we registered the redis-server executable as a service, it will start Redis on boot in the background.
Installing Redis on Mac OS X (Snow Leopard)
I’ve tested this with Snow Leopard and Maverick Meerkat but there shouldn’t be a reason why it wouldn’t work with any Linux-based machine.
Download, extract and compile Redis, as per official documentation, with:
$ wget http://redis.googlecode.com/files/redis-2.2.11.tar.gz
$ tar xzf redis-2.2.11.tar.gz
$ cd redis-2.2.11
$ make
$ sudo make install
This installs your Redis binaries to your /usr/local/bin folder. Now, move the Redis config file some where more system-wide:
$ sudo mv redis.conf /etc/redis.conf
You should now be able to run redis-server from any location in Terminal, but if you want to use your config file then just append it to your command like so:
$ redis-server /etc/redis.conf
For the last part, we don’t want to have to start Redis each time we want to use it, so we’re gonna have to launch it on startup. Mac OS X provides launchctl for this specific purpose.
All you have to do is add this file to your /Library/LaunchDaemons folder (credit goes to Tommy Pitale’s blog post. I have already configured it to work with the setup described in this post. I created it with the file name io.redis.server.plist.
Do make sure to create the /var/log/redis folder and you should be good to go once you start it up using this command:
$ sudo launchctl load io.redis.server.plist
Do remember to use sudo, otherwise your Redis instance will not be able to output to the log files. You can see a live trail of your output by executing this command:
$ tail -f tail -f /var/log/redis/error.log /var/log/redis/output.log
Update (6 July, 2011): updated to the latest version of redis (2.2.11), cleared up notes on running redis with users’ config.
Update (19 July, 2011): added instructions to get Redis to start up automatically.