mrd creates a virtual disk in memory, and runs an instance of MySQL on it. The main application is running tests: no matter how fast your hard drive is, it will never be as fast as RAM. Since test data is volatile anyway, why not use the fastest medium available. As an added bonus, because it prevents all these volatile writes from going to disk, it can increase the lifespan of your SSD.
While mrd
is great, it's only great if you use it all the time. So in this article I'll share a few tips that have made using mrd
a much more pleasant experience for me.
Similar to our previous article on Mailcatcher, If you have a reasonably recent version of Linux or Mac OS X, you probably have Ruby installed. If not, you will have to install Ruby first. Once you have Ruby installed:
# If you are using the system's Ruby:
sudo gem install mrd
# If you use rbenv/rvm/etc:
gem install mrd
If you use rvm
, rbenv
or chruby
, you will first need to create a wrapper script. I put mine in ~/.bin/launchd-mrd
:
#!/bin/bash
export PATH="$PATH:/usr/local/bin"
source /usr/local/share/chruby/chruby.sh
chruby 2.1
mrd
Make the script executable:
chmod +x ~/.bin/launchd-mrd
Launch it:
~/.bin/launchd-mrd
# Created Ramdisk at /dev/disk4
# Formatted Ramdisk at /dev/disk4
# Mounted Ramdisk at /Volumes/MySQLRAMDisk
#
# [...]
#
# Starting MySQL server
# MySQL is now running.
# Configure you client to use the root user, no password, and the socket at '/Volumes/MySQLRAMDisk/mysql.sock'.
# Just close this terminal or press ^C when you no longer need it.
Great! It works perfectly. Let's now create a daemon to automatically start it on boot.
Create the startup script:
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
<key>Label</key>
<string>com.$USER.mrd</string>
<key>Program</key>
<string>$HOME/.bin/launchd-mrd</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/com.$USER.mrd.err</string>
<key>StandardOutPath</key>
<string>/tmp/com.$USER.mrd.out</string>
</dict>
</plist>
" > ~/Library/LaunchAgents/com.$USER.mrd.plist
Launch it:
launchctl load ~/Library/LaunchAgents/com.$USER.mrd.plist
You should see the new shiny icon right on your desktop:
If you run into any trouble, look at the logs:
/tmp/com.$USER.mrd.out
/tmp/com.$USER.mrd.err
You can now open your config/database.yml
and update the test
section:
test:
adapter: mysql2
encoding: utf8
collation: utf8_unicode_ci
host: localhost
database: NAME
username: root
password:
socket: /Volumes/MySQLRAMDisk/mysql.sock
Run the tests:
cd ~/project
RAILS_ENV=test bundle exec rake db:create
bundle exec rake db:test:prepare
bundle exec rake test
..............................................................
..............................................................
...
Yeah \o/ This works!
Wouldn't it be better if we could automate the database creation/preparation as well? After all, you might have multiple projects, and you don't want to have to recreate the test database each time, load the schema, etc... So let's automate all that.
Create a new script ~/.bin/prepare-test-dbs
:
#!/bin/bash
# Load your preferred Ruby Version Manager
export PATH="$PATH:/usr/local/bin"
source /usr/local/share/chruby/chruby.sh
source /usr/local/share/chruby/auto.sh
# Wait until 'mrd' is actually loaded, and MySQL running
until [[ -S /Volumes/MySQLRAMDisk/mysql.sock ]]; do
sleep 1
done
# Go through each project, and:
# - create the database
# - load the schema
# - clear logs/*
# - clear tmp/*
for dir in ~/projects/project1 \
~/projects/project2 \
~/projects/projectN; do
cd "$dir"
RAILS_ENV=test bundle exec rake db:create
bundle exec rake db:test:prepare
bundle exec rake log:clear
bundle exec rake tmp:clear
done
Make it executable:
chmod +x ~/.bin/prepare-test-dbs
And create the startup script:
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
<key>Label</key>
<string>com.$USER.mrd-prepare</string>
<key>Program</key>
<string>$HOME/.bin/prepare-test-dbs</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/com.$USER.mrd-prepare.err</string>
<key>StandardOutPath</key>
<string>/tmp/com.$USER.mrd-prepare.out</string>
</dict>
</plist>
" > ~/Library/LaunchAgents/com.$USER.mrd-prepare.plist
Now, each time your start your computer:
mrd
will launch a MySQL instanceRun the tests:
cd ~/projects/project1
bundle exec rake test
..............................................................
..............................................................
...
You're all set!
That's it for today. Cheers ;)