Installing Merb 4

Posted by yossarian

I took a crack at installing Merb today, just to see how it works out. It’s a very minimal Ruby framework which in my (admittedly not very scientific) testing appears to be a lot faster than Rails, especially under conditions of high concurrency.

To get it running, I followed the instructions at the Merb book which is currently a work in progress at http://4ninjas.org. A quick tip: due to a dependency on extlib 0.9.3, the sake edgy technique didn’t work for me at first. I got it all running happily by doing the following.

First, install the Git source-code management tool and the Debian build tools if you don’t already have them:

sudo apt-get install build-essential git-core
sudo gem install rack mongrel json erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory  english addressable templater

Update: in the last few weeks gem dependencies have changed and you need to ensure you’ve got some specific versions available:

sudo gem install ruby2ruby --version=1.1.8
sudo gem install ParseTree --version=2.1.1

You’ll also need to ensure that you’ve got the MySql headers available in order to build the datamapper MySql libraries.

sudo apt-get install libmysqlclient15off libmysqlclient15-dev
git clone git://github.com/sam/extlib.git  
git clone git://github.com/sam/do.git

cd extlib
rake install ; cd ..
cd do
cd data_objects
rake install ; cd ..
cd do_mysql  # || do_postgres || do_sqlite3
rake install

For whatever reason, DataMapper 0.9.4 has a dependency on Merb-core 0.9.3, so you’ll need to install it and then proceed to build the newest DataMapper:

sudo gem install merb-core

git clone git://github.com/sam/dm-core.git
git clone git://github.com/sam/dm-more.git

cd dm-core ; rake install ; cd ..
cd dm-more
rake install; cd ..

After that stuff, the

sudo gem install sake
sake -i 'http://edgy.4ninjas.org/edgy.sake'
sake edgy:install packages="merb-stack"

commands worked just fine for me.

Bonus: install CouchDb, the wicked distributed database system which is currently an Apache incubator project.

sudo apt-get install build-essential erlang libicu38 libicu-dev libmozjs-dev
wget http://www.apache.org/dist/incubator/couchdb/0.8.0-incubating/apache-couchdb-0.8.0-incubating.tar.gz
tar -xvzf apache-couchdb-0.8.0-incubating.tar.gz 
cd apache-couchdb-0.8.0-incubating/
./configure
make && sudo make install

You can set up the CouchDb datastore as a service, with its own user, like this (thanks to these instructions, slightly modified to avoid the creation of a “couchdb” home directory):

sudo useradd couchdb
sudo mkdir -p /usr/local/var/lib/couchdb
sudo chown -R couchdb /usr/local/var/lib/couchdb
sudo mkdir -p /usr/local/var/log/couchdb
sudo chown -R couchdb /usr/local/var/log/couchdb
sudo mkdir -p /usr/local/var/run
sudo chown -R couchdb /usr/local/var/run

sudo cp /usr/local/etc/init.d/couchdb /etc/init.d/
sudo update-rc.d couchdb defaults
sudo /etc/init.d/couchdb start

After that, go to http://localhost:5984/_utils/index.html and you can administer your new distributed datastore. Of course, you could just ignore CouchDb and use Merb with a more “normal” database server like Mysql or Postgres.

If any of the version dependencies change again please leave a comment and I’ll update these instructions until Merb 0.9.4 is a little easier to get.

Mod_rails and full page caching with a custom cache location

Posted by yossarian

We’ve recently moved a couple of Hyperactive sites to run on mod_rails, a recently released Apache module which allows much easier deployment of Rails sites which run on a single box. Using it gives the nice happy glow that you get from using Apache’s PHP module – dump your project code into a directory accessible by Apache and it executes. This contrasts with the more complex process of setting up and maintaining a Mongrel cluster using mod_proxy_balancer (although that option still has a lot to recommend it, especially if you want to run a site across multiple servers in your data centre).

Everything works very well so far, but I did run into one problem. If you’re using full page caching in Rails, mod_rails automatically finds your cache files and tells Apache to render them from disk instead of hitting the Rails stack if a cache for a given URL. However, it only finds the cache files if they’re in the default location (RAILS_ROOT/public). Personally I find the default location a bit messy, since the cache files get mixed in with all the other stuff in your /public directory – so I tend to put cache files at RAILS_ROOT/public/system/cache to keep things clean.

config.action_controller.page_cache_directory = RAILS_ROOT + "/public/system/cache/"

The trouble was that mod_rails didn’t pick up these cache files by default, so I went back to Apache rewrite rules. I dumped in my old rewrite rules from my Mongrel configuration, and everything seemed to be working. Cached pages were served statically, due to this rewrite rule:

# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ /system/cache/$1.html [QSA]

I haven’t seen anyone else report this problem, but I had one bit of trouble. My application obviously uses a POST request rather than a GET request to send an update to the server, but the route is otherwise the same. Attempting to edit a piece of content on the site resulted in Apache intercepting the call and just showing the content again, bypassing the “update” method call and making the site’s content impossible to edit. I have no idea why this is the case with mod_rails but didn’t happen with Mongrel, but whatever – I’ve just added the following rewrite condition to my Apache configuration and it seems to work fine:

# Rewrite to check for Rails cached page
RewriteCond %{THE_REQUEST} !^POST
RewriteRule ^([^.]+)$ /system/cache/$1.html [QSA]

This means that Apache won’t attempt to pull the file from the cache for any POST requests (like updates), making it all work again.