29 08 2008

brandevents.ie - stop spamming me!

I received an email from brandevents.ie today. It was the third unsolicited email they sent me. I complained after receiving the first mail on 18 April 2008, but they keep sending me mail! An interesting feature of their email marketing is that they choose not to bcc the recipients, so I can see all the other lucky people who are in with a chance of winning a trip to New York (in a competition for the title of ‘Best Dressed Commuter in Dublin City’)

I rang brandevents, and when I asked to speak to the person (Scott) who sent the email I was told that there was no one called Scott working there…

I forwarded the email I received today to the Data Protection Commisioners, hopefully they will fine them or something.

13 06 2008

how to fix git-svn if the svn repo moves

I’m using git-svn at the moment, as the owner of a project I’m working on is using subversion. The svn server has just moved to a new domain name. Unfortunately this broke git-svn as I couldn’t rebase (got an error like this:
“RA layer request failed: PROPFIND request failed on ’/svn’: PROPFIND of ’/svn’: 200 OK (http://$OLD_DNS_NAME) at /usr/local/bin/git-svn line 1839” )

Just editing .git/config and changing the url for the svn repo doesn’t work as rebasing will produce the following error: Unable to determine upstream SVN information from working tree history.

The solution to this problem is as follows:

  • edit the svn-remote url URL in .git/config to point to the new domain name
  • run git svn fetch
  • change svn-remote url back to the original url
  • run git svn rebase -l to do a local rebase (with the changes that came in with the last fetch operation)
  • change svn-remote url back to the new url
  • git svn rebase should now work again!

02 03 2008

make_resourceful is awesome!

I have started using make_resourceful to DRY up my controller code. If you use the standard RESTful controllers, make_resourceful can reduce your controller to this:
class AccountsController < ApplicationController
  make_resourceful do
    actions :all
  end
end
That’s pretty sweet. Of course often a controller might need to be modified slightly, for example I needed to do some set up work to display a google map for a resource (using the ym4r_gm plugin). To set up the @map variable before rendering the view:
make_resourceful do
  actions :all
  before :show do
    # Set up the @map variable here
  end
end
I then needed to access the names of some related models, rather than just their id’s, and wanted to keep the generated SQL statements efficient. Turns out that’s easy too, Just override the current_objects (for index), or current_object (for show) methods in your controller like so (best to have them as private methods):
private
def current_objects
  @current_objects ||= Location.find(:all, :include => :related_object)
end

Note that ||= is used instead of = in case the object has already been cached.

Depending on how much customisation is required, it might turn out that using the standard REST controller is actually more efficient, but for a lot of the projects that I am working on that is not the case, and using make_resourceful makes my life easier :)

23 02 2008

Rails deployment with Vlad, Git, Thin, and Nginx

This is how I deploy a rails app to a single server

Note that I use variable names like $APP_NAME, or $REPO_IP, these need to be replaced by values appropriate for your app. The names are fairly self-explanatory. For consistency I always use full paths to folders, so $REPO_PATH might be replaced by /home/git/repo/blog.git

Here goes…

  • If you don’t want to have to type in the password when checking out the app from your code repo, follow these instructions to set up ssh key pairs.
  • Install vlad on development machine:
    sudo gem install vlad
  • Install thin on server AND dev machine
    sudo gem install thin
  • Add the following to a rake file in your rails app (lib/tasks/app.rake in my case):
    begin
      require 'vlad'
      Vlad.load :scm => :git, :app => :thin
    rescue LoadError
      # do nothing
    end
  • At the moment the Vlad gem doesn’t ship with any thin-specific tasks, but fortunately the thin gem does (in example/vlad.rake). This rake file needs to be copied into the lib/vlad directory of the installed vlad gem. On leopard this means the following command, Linux (and possibly Tiger?) users will need to use different paths:
    sudo cp /Library/Ruby/Gems/1.8/gems/thin-0.6.3/example/vlad.rake \
        /Library/Ruby/Gems/1.8/gems/vlad-1.2.0/lib/vlad/thin.rb
  • Add deployment settings to config/deploy.rb:
    set :domain, "$SERVER_IP" 
    set :deploy_to, "$DEPLOYED_APP_PATH" 
    set :repository, "$REPO_IP:/$REPO_PATH"
  • Create production database on the server, then edit the production settings in database.yml, specifying the username and password you use to connect to the database as well as the path to the socket. On Ubuntu the mysql socket is at /var/run/mysqld/mysqld.sock , as opposed to /tmp/mysql.sock on OS X
  • To create the directory structure to which the rails app will be deployed, as well as a configuration file for the application server, run the following command from the development machine:
    rake vlad:setup
  • If you open up $DEPLOYED_APP_PATH/shared/thin_cluster.conf on the server, you will see that thin is going to use unix sockets, which are faster than TCP ports.
  • To checkout the project, run any migrations and start the app servers, run the following command from your dev machine:
    rake vlad:update vlad:migrate vlad:start_app
  • If you have gotten this far, your app will be up and running, but not useable, as the webserver isn’t set up.
  • Here’s my standard vlad:deploy task, which I add to my rakefile:
    namespace :vlad do
      desc "Showtime! pull from git then (re)start the app servers" 
      task :deploy => [:update, :migrate, :start_app]
    end
  • Install nginx if you haven’t already:
    sudo apt-get install nginx
  • The Ubuntu and Debian nginx packages have a nice convention for setting up and enabling multiple domains with separate config files. I modify this template configuration file by replacing the $VALUES with my own, then save it to /etc/nginx/sites-available/$APP_NAME
  • I also make a few changes to the default nginx.conf in /etc/nginx/nginx.conf – see here
  • The nginx configuration can be checked by running
    sudo nginx -t
  • Assuming there were no configuration errors, the nginx config file for the rails app can be symlinked into the sites-enabled directory
    sudo ln -s /etc/nginx/sites-available/$APP \
      /etc/nginx/sites-enabled/$APP
  • Reload the nginx configuration
    sudo /etc/init.d/nginx reload

The app should now be up and running with Nginx proxying it on port 80… success! From now on, to update the deployment just push to the git repo then run

rake vlad:deploy

21 02 2008

Setting up an edge rails app

Here is my recipe for setting up a rails app, using edge rails and git.

  • Check out edge rails. I use ~/src/ext to hold source checkouts of projects which aren’t mine (mine go in ~/src)
    git clone git://github.com/rails/rails.git
  • Then create the rails app. Rails now defaults to sqlite, so if you want to use mysql you will need to pass in -dmysql to the following command:
    ruby ./ext/rails/railties/bin/rails $PROJECT
  • cd into the rails app and create a new git repository
    git init
  • To stop git from adding logs and other artefacts to the repo, create a .gitignore file in the $PROJECT folder, containing the following lines
    log/*.log
    tmp/**/*
    .DS_Store
    doc/api
    doc/app
    db/schema.rb
  • Unfortunately git won’t track folders with no content, and as we are ignoring everything in the log/ and tmp/directories, git will see them as empty and they won’t be checked out (same for other empty directories: db/ lib/ vendor/ app/models app/views but when content is added to them they will be tracked). This means that if you check out (clone) the project and run ./script/server the webserver won’t start and there will be an error saying “Rails Error: Unable to access log file”. The solution to this is to create and add a file called ’.gitignore’ to the log/ and tmp/ directories:
    touch log/.gitignore tmp/.gitignore
  • Now add all the newly created files, and commit them to the repository
    git init
    git add .
    git commit -m "empty rails project import"
  • There is now a .git/ directory in the $PROJECT folder, this folder stores the repository. I like to store my code on another machine though so I copy the repo to a remote server:
    scp -r $PROJECT_DIR user@$SERVER_IP:/desired/path/$PROJECT.git
  • The app can now be checked out from the server:
    git clone user@$SERVER_IP:/desired/path/$PROJECT.git
  • To run an app on edge rails, you need to import edge rails into vendor/rails. I use braid to track edge like so:
    braid add git://github.com/rails/rails.git vendor/rails
  • This creates a branch called braid/track which can be merged back into the current branch like so
    git merge braid/track
  • Start the server
    ./script/server

The rails app is now running on edge!

04 02 2008

My Slicehost server setup

I set up a new slice today using the following steps, most of which have I got from these three articles.

I use Ubuntu Gutsy on my servers. This setup gets me to the stage where I can deploy rails apps (which will be the topic of another post). Note that user specific values are preceded by the dollar sign, so for example I would replace $USERNAME with ciaran.

  • Log in as root
  • Add universe and multiverse repos to the ubuntu archives in /etc/apt/sources.list
  • Update packages
    apt-get update
    apt-get upgrade
  • Change root password (I use pwgen to create passwords) by running ‘passwd’ as root
  • Change default text editor to vim by running
    update-alternatives --set editor /usr/bin/vim.basic
  • Add a standard user:
    adduser $USERNAME
  • Allow standard user to use sudo to run commands as root by adding the following line to the end of the text file that is opened when ‘visudo’ is run as root:
    $USERNAME  ALL=(ALL) ALL
  • Switch to the non-root user
  • Copy public key from my workstation to the server:
    scp ~/.ssh/id_dsa.pub $USERNAME@$SERVER_IP:
  • Then on the server add it to the /home/$USERNAME/.ssh/authorized_keys file:
    cat id_dsa.pub >>.ssh/authorized_keys
  • Log in to the server as the non-root user, there should be no password authentication now that the public key has been authorized
  • Disable root login over ssh, and disallow password logins, among other things, by making sure the following lines exists in /etc/ssh/sshd_config:
    PermitRootLogin no
    PasswordAuthentication no
    X11Forwarding no
    UsePAM no
    UseDNS no
    AllowUsers $USERNAME
  • Restart the ssh server:
    sudo /etc/init.d/ssh restart
  • Install rails + dependencies. I wouldn’t actually use the ubuntu rails package, but if you install it it pulls in some dependencies which are useful.
    sudo apt-get install rails libopenssl-ruby \
      libopenssl-ruby1.8 ri1.8 ruby1.8-dev \
      build-essential zip unzip
  • Install mysql + extras (set the root mysql password while you are at it!)
    sudo apt-get install mysql-server mysql-client \
      libmysqlclient15-dev libmysql-ruby
  • If you don’t want to use InnoDB then edit /etc/mysql/my.cnf, and uncomment the following line:
    #skip-innodb
  • Restart mysql
    sudo /etc/init.d/mysql restart
  • Download and install rubygems, then symlink gem1.8 to gem:
    sudo ln -s /usr/bin/gem1.8 /usr/bin/gem
  • Symlink irb1.8 to irb:
    sudo ln -s /usr/bin/irb1.8 /usr/bin/irb
  • Install git
    sudo apt-get install git-svn
  • Install ssmtp then edit the config file as follows:
    root=$GMAIL_USERNAME@gmail.com
    mailhub=smtp.gmail.com:587
    AuthUser=$GMAIL_USERNAME@gmail.com
    AuthPass=$GMAIL_PASSWORD
    rewriteDomain=gmail.com
    UseSTARTTLS=YES
    hostname=$HOSTNAME
    FromLineOverride=YES

24 01 2008

My blog on Rails!

I have taken Geoffrey Grosenbach’s advice and written my own blog software. It’s a pretty basic application right now, with the following features:

  • Single model (article), no comments yet
  • Haml used for view code, I prefer this to erb as it is nicer to write, and results in properly indented html
  • Markdown Textile used for editing articles in plaintext
  • Deployed using Vlad

My next ask is to add an RSS feed, so that my many readers will be able to subscribe using an RSS reader :)