Something to note, Rails typically is run in three modes:
- Test - Mode typically used for Unit Tests.
- Development - Development environment, includes verbose errors and stack traces.
- Production - Settings are as if you were running in this application in a production environment.
Now obviously, if you've done something custom like `export RAILS_ENV=production` this would be different. Additionally, explicitly casting the mode in which something like the Rails console runs (example: rails console production) will change the default behavior or mode, rather.
What does all this mean? Well, really it means that you want to develop in development mode and run a production application in production mode. Pretty simple huh?
Time to configure for Unicorn versus the default Webrick web server. If you are asking yourself "why", the answer is fairly straightforward. Unicorn is meant for production and handles a large amount of requests better and overall, is more configurable. For the purposes of this tutorial, we will use Unicorn for both development and production.
I want to demonstrate two ways of doing this. The first is by using a startup shell script. The other, for the purposes of an introduction to Rake tasks, will be to actually create a Rake task to start the application in lieu of a shell script.
Startup shell file:
Modify your Gemfile by uncommenting the line with the Unicorn gem. Also, while we are at it, let's uncomment the Bcrypt gem as well:
Run `bundle install`:
Make the startup script executable and fire it up:
The line `rvmsudo bundle exec unicorn $*` means...
- rvmsudo - Allows you to run sudo commands while maintaining your RVM environment.
- bundle exec = Directs bundler to execute the program which, automatically 'require'(s) all the gems in your Gemfile.
- unicorn - Unicorn service.
- $* - Any arguments passed to the script will be executed as part of the command inside of the script. Example: ./start.sh -p 4444 translates to - `rvmsudo bundle exec unicorn -p 4444` and would start the server on port 4444.
Alternatively, we can just easily package this up as a Rake task. A Rake task is a repeatable task that can be executed using the `rake` command. Nothing magical, it just harnesses Ruby goodness to convert your task definitions into an executable command.
There is an excellent tutorial on Rake available via the Railscasts site. For our purposes, let's create a Unicorn rake file. Do this under /lib/tasks and use the `.rake` extension.
Presumably, you may wish to have multiple tasks available to the Unicorn namespace. For instance, if you'd like to both start and stop the Unicorn service it would be beneficial to create a namespace titled "unicorn" with multiple tasks inside it. For the purposes of this tutorial, I will only cover building a start task as you can easily expand upon this. Also, since we are running the Unicorn service in an interactive mode, you can hit ctrl+c to stop it.
I would like to note that having a start and stop task is very beneficial if you are running Unicorn detached (non-interactive), where the service runs in the background.
Moving along, here is the task...
Lines 1 & 9 - Begin and end the unicorn namespace definition.
Line 3 - Describe the task (useful at the console).
Line 4 - Define the task with the first argument "task" and any additional definitions (comma separated) are arguments. In this example, we except a port argument.
Line 5 - We code some logic that says, port_command will equal either an empty string or "-p <port number>" and if a port number is not provided (nil) it will equal an empty string.
Line 6 - This is a shell command that appends the result of port_command to `rvmsudo bundle exe unicorn`.
Let's list our tasks and see if it is available:
Success! Notice how the description and command format are auto-magically taken care of for you.'
You can run this in one of two ways.
`rake unicorn:start` (starts the Unicorn service on port 444) OR....
`rake unicorn:start` (starts it on the default port, 8080)
To recap, we've shifted off of Webrick and over to Unicorn. Also, we've introduced the concept of a Rake task.
Stay tuned for more parts in this series...