Passenger, AKA mod_rails
There are a number of posts (one, two) out there on getting Phusion's Passenger up and running on OSX (Leopard). I decided to give it a go, and was pleased to discover several things:
- Despite reports to the contrary, Passenger installed just fine with Leopard's built-in Apache (I'm running Apache 2.2.8).
- Setup is very easy, as advertised.
- My default doc root(~/Sites) is works exactly as it did before. I do some HTML and PHP work there, so it was key that it continue to work properly.
Since the install process itself is quite easy, I wanted to offer a few tips for utilizing Passenger in a typical dev environment -- i.e., what you need after you get your first Passenger-powered Rails app up and running.
Your Brain on Passenger
As you know,
script/server starts your Rails app on a specific port. If you bounce around between a number of applications at any one time, you're probably used to either starting them on different ports, or control-c'ing your current mongrel, cd'ing to another app's directory, and script/server'ing again. This familiar pattern changes when you're running passenger. All your apps are available at any one time, as long as you have your vhosts configured.
If you're like me, you usually hit your currently running Rails app on http://localhost:3000. That also changes when you're running Passenger. Instead, you'll hit a unique URL for each app, which you've configured in /etc/hosts to just go to 127.0.0.1
Setting up a new app
I set up a lot of Rails apps in my dev environment. With Passenger, in exchange for the on-demand convenience of accessing any of your apps any time, there are a few additional setup steps to take whenever you introduce a new app into your dev environment.
- create your rails project as usual
- add a new vhost. I configure mine in
- add the host in /etc/hosts
- restart apache: sudo apachectl restart
Here's a vhosts example with two apps I'm running locally. You can set up as many apps as you want this way:
Two things to note here:
- The ErrorLog line is optional. If you don't include it, the error output for this app will go to
/private/var/log/apache2/error.log. Not that that's bad, but you're probably not used to looking for Rails logs there.
- I decided to go with the convention of dev.[PRODUCTION_URL].com. You can use anything here, as long as it matches up with an entry in /etc/hosts (see below)
And here's an example
/etc/hosts addition to match the two virtual hosts above:
That's it! Go to (for example) http://dev.hotspotr.com, and you're hitting you local development app. There is nothing to start and stop. The first request for any app you hit will take a moment. Subsequent requests will feel quite snappy.
Let's Set up some Aliases to Make it all Flow
Here are the aliases I added to my
.bashrc file to give me quick access to everything I needed for a new, Passenger-centric workflow in my development environment:
# Use this in any RAILS_ROOT dir. That restart.txt file tells mod_rails to restart this app.
# You'll want to do this when (for example) you install a new plugin.
alias restart_rails='touch tmp/restart.txt'
# By default, your app's error log now goes here. Unless you configure your apps otherwise,
# it's helpful to have an alias to take you to your error log quickly.
alias apache_logs='cd /private/var/log/apache2/'
# You'll be adding to your vhosts configuration everytime you introduce a new Rails app.
# Might as well make it a shortcut
alias vhosts='sudo vi /private/etc/apache2/extra/httpd-vhosts.conf'
# Dito with hosts
alias hosts='sudo vi /etc/hosts'
# You'll need to restart apache whenever you make a change to vhosts.
# You can also click System Preference->Sharing->Web Sharing, but this is quicker.
alias apache_restart='sudo apachectl restart'
Hotspotr -- my community-driven WiFi hotspot site -- announced a content-providing partnership with LightPole today. You can read the press release over at http://lightpole.net/press/index.html.
Hotspotr lists over 8,000 user-contributed WiFi hotspots. LightPole provides a mobile client you can use to browse Hotspotr from your mobile phone using an interactive, maps-based interface:
You can download the LightPole mobile client for free from the Hotspotr homepage.
Separately, Hotspotr is also taking advantage of the Google Maps streetview functionality. For locations where streetview is available, you will have the option to browse the 3-d streetview imagery:
See an example at the Dolores Park Cafe in San Francisco.
Staging environments are the perfect excuse to dig into new server configurations, and to play around with tools like Deprec. I have covered the gruesome technical details of the process over at Andre on Tech:
Overall, I'm impressed with how much deprec does for you. I had my staging environment setup in a few hours. Enjoy!
For a recent Rails project, I had to use PostgreSQL instead of the standard MySQL for the database. Setting up Postgres on Mac OS 10.5 has some quirks, which I will share with you here.
- There are three primary ways to get PostGRES onto Leopard: a pre-built binary, MacPorts, and source. My choice was to build with source. There are several good posts on building from source:
I do not recommend creating a separate user to run postgres. Doing so clutters your startup screen with another user, and requires you to su to that user to start the database. Instead:
1) install Postgres as root
2) after install, from the command line: chown -R andre /usr/local/pgsql/data. The -r flag changes the ownership recursively. Obviously, substitute your own username for "andre" in the example.
Since I don't use PostGres all the time, I don't want it to be started up automatically. Instead, I set up two aliases in by .bashrc:
alias startpostgres='/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile start'
alias stoppostgres='/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile stop'
when you start postgres, you'll probably get the dreaded "shared memory error," which looks like this:
FATAL: could not create shared memory segment: Cannot allocate memory
DETAIL: Failed system call was shmget(key=1, size=1081344, 03600).
HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory or swap space. To reduce the request size (currently 1081344 bytes), reduce PostgreSQL's shared_buffers parameter (currently 50) and/or its max_connections parameter (currently 10).
some resources will tell you to edit the /etc/rc file, which is incorrect for Leopard. Instead, create
/etc/sysctl.conf (if it does not already exist -- mine didn't), and add the following lines:
You'll need to su to root to create
Have fun with Postgres!
I have a geocoding recipe coming out in Pragmatic’s Advanced Rails Recipes . The recipe is titled “Finding Things by Location,” and it offers how-tos and best practices on using my GeoKit plugin to, well, Find Things by Location. The most recent PDF of the beta book includes my recipe along with over 30 other recipes by community leaders like Chris Wanstrath, Dan Benjamin, and Geoffrey Grosenbach, to name just a few.
Much of what Rails provides to get your apps up and running isn’t optimized for performance. It’s crafted to be more efficient for developers, not more efficent at runtime. before_filter callbacks on your RESTful controllers to get the current object? That’s an extra database call. All those nifty plugins you are using to kickstart your app? They probably generate far more SQL (and slower SQL) than if you coded the same functionality ad-hoc. ActiveRecord itself is slow compared to raw SQL and object instantiation.
If your project grows huge — 10’s of millions of PV/day huge — you’re gonna have to revisit some of that stuff. Some of it you can compensate for with smart caching techniques and more hardware. And some of it you will have to throw away and rewrite. If you get really huge, you’re going to have pay back some of the technical debt you incurred by choosing a tool like Rails.
Yes, using a tool like Rails incurs some debts. But just like the rest of the world, there are good debts and bad debts. If you’re smart about the kind of debt you take on, you can build far more, and build it faster.
Many of your projects will never reach the level where you need to “pay back” for all that developer productivity you enjoyed on the front end. That means you can try more ideas, and (hopefully) fail fast at the more speculative ones. If some of your projects do need to scale radically (beyond the basics of better caching, more hardware, etc), you have an incredible amount of upfront productivity you can leverage against that work of — say — optimizing some key queries by hand. As long as you go in with eyes wide open and realistic expectations, then I say that’s a smart kind of technical debt.
We’ve just launched PlaceShout (http://placeshout.com) – a “cheatsheet”-style summary of places around town, created by you and arbitrated by the community. Now you can see what’s important about a place without wading though stories about someone’s neighbor’s dog.
If you have ever been anywhere, you’ll enjoy making shoutouts. You’re limited to 100 characters, so save the long-winded narratives for someplace else.
You are probably thinking that PlaceShout’s signup process is a long, arduous process. Let me be the first to assure you that it is not. If you have one of those new-fangled OpenIDs, you can sign right in. Because we’re web 2.0 like that.
The easy doesn’t stop there. To make a shoutout, just type it in along with and the name of the place:
Confirm the place:
Like magic, the shoutout appears:
People are shouting out places in small towns and big cities…
- According to Megan, Welsh’s Pizza of Pender, NE (pop. 1,145) is the “Best place in the tri-county for pizza!”
- Jim Benson is living the big city life in Seattle, WA (pop. 3,263,497), and spreading the news that Cafe Besalu’s “Ginger biscuits will make you happy”.
Where are most of the shouters? Right now Ann Arbor, Michigan is in first place. You can see all the cities and add your city here.
Like maps? We have a map. And it has nifty directional arrows:
Try it out now: http://placeshout.com
Have you noticed how much easier it is to remember directions in your own city? Think about the last time your printer ran out of ink and you had to jot directions to a restaurant on a post-it. Compare that to writing out directions from a hotel to a restaurant in an unfamiliar city.
It's a lot easier on familiar turf. Why? Near home, the directions are anchored by points of familiarity in your mind. You already know how to get to someplace nearby, so you can use that as a ready point of reference. Closer to home, you get to use all kinds of reference points: your work, familiar street names, the park you go to, etc. Because that's the way your brain works. In your brain, everything is a relative reference.
This is equally true if you are communicating directions to someone, rather than just writing them down for yourself. The better you know the person, the easier it is: "go like you're headed to work, but turn left just before that Thai restaurant you like." Not only are the directions concise, they are simple enough that you probably don't need to write them down. Communicating is a lot easier when there are shared experiences, reference points, and a sense of "knowing what the other person knows."
There are lessons in here somewhere for those of us who create software. After all, we spend a lot of time with our computer trying to find things, either on the computer (photos, spreadsheets) or with the computer (a book on Amazon, that page you Delicious'd -- or did you mark it in Google Reader?). I often think of this when I'm using Delicious. I know I bookmarked something, but wading through the tag cloud to find it again takes too long. I usually end up finding it with a few Google searches. When the first search fails, there's usually something in those first results which triggers my memory on the keywords that will retrieve it.
Can software infer what is familiar terrain for us, and provide navigation relative to that? Can Google or Delicious know what my mental "anchors" are, and help me find stuff from there?
An OS-level example: I have a dozen or so Ruby on Rails projects in /Users/andre/projects/rails/, and I spend a lot of time in the immediate subdirectories. If there were a heat map of the places I spend time in, this directory would be hot. Would that be useful as a navigational device? Possibly. If a place got hot enough, the OS could ask me to label it in a way that's meaningful to me. I might use that as a jumping-off point as long as spend a lot of time on Rails projects.
Obviously there are pitfalls when trying to get a computer to guess what you're trying to do, or what's important to you (R.I.P Clippy). Still, there are bound to be payoffs for trying to get the computer to present navigation the way you think, rather than how it computes. A good start is to think about how our brains tend to remember things clustered relative to familiar points of reference.