Git and Rails : Switch your database.yml when changing branch
As a lot of people, I think, I have different database.yml file according to git branch I’m working on. I was constantly switching it manually until I discovered that git has more hooks that I thought.
I set up a post-checkout hooks script to automagically switch my database.yml when checking out a branch.
It is a simple script that recover the branch name a do a symlink.
if i checkout branch master it will look for a file named config/database.master.yml and create a symlink to config/database.yml
here it is :
#! /bin/sh
#
# .git/hooks/post-checkout
BRANCH=`git symbolic-ref HEAD 2> /dev/null | sed -e 's/^.*\///'`
GITPATH="`git rev-parse --git-dir 2>/dev/null`/.."
if [ "$BRANCH" == "" ]; then
echo "no branch name. do nothing"
exit 0
fi
if [ -f "$GITPATH/config/database.yml" ] && [ ! -L "$GITPATH/config/database.yml" ]; then
echo "database.yml exists and not a symlink. do nothing."
exit 0
fi
echo "look for $GITPATH/config/database.$BRANCH.yml"
if [ -f "$GITPATH/config/database.$BRANCH.yml" ]; then
echo "switch database configuration file to config/database.$BRANCH.yml"
rm -f "$GITPATH/config/database.yml";
ln -s "$GITPATH/config/database.$BRANCH.yml" \
"$GITPATH/config/database.yml"
fi
Using git to mirror a SVN repository on Leopard 3
Working for a new client on a Rails project, I decided to give a shot at Git.
I’m working with an other developer who holds the svn repository. He is the only person allowed to commit to the trunk and I have to commit to my own branch. At first, this doesn’t seemed to be a problem. But there is a lot of files modified every day on the trunk and I’m constantly merging from the trunk to keep my branch up to date. Git seems to have some nice features that could help me to avoid those constant merges.
I writing this article while installing git so I don’t already know if it is the solution to my troubles. I just read this article and it convinced me to give git a try.
I have to mention that I never worked with git before so I will discover git with this project and we’ll see if it’s reasonable. I heard about git on rubyinside blog a few weeks ago.
So, as I’m on leopard, the easiest way (for me) to build git is macports so let’s do it.
sudo port install git-core +svnThis installs all git git-svn and gitk. All ran smoothly for me. If it fails try this install tutorial for leopard.
Now it’s installed properly I need to build my git project from subversion repository
daiquiri% git svn init https://repos.../trunk
Initialized empty Git repository in .git/It doesn’t checkout the sources so let’s check this previously mentioned article to see what I do next.
All right, I need to figured what is the HEAD revision number to go next :svn info https://repos.../trunkgit-svn fetch -r3741
.
.
...The checkout happens...
.
.
r3741 = b444a88efc7248dfdd5f96a7dd7e36165a0f3ed6 (git-svn)
Checking 4130 files out...
100% (4130/4130) done
Checked out HEAD:
https://82.240.32.108/svn/eco-sys/trunk r3741
It seems all went ok and that my git project is ready to go.
I little config seems to make things a little prettier. I took this from here
git config --global user.name "Antonin Amand"
git config --global user.email "aamand@gwikzone.org"
git config --global color.status auto
git config --global color.diff auto
git config --global color.diff auto
git config --global color.branch auto
git config --global merge.tool opendiff
git config --global core.excludesfile ~/.gitignore
echo ".DS_Store" >> ~/.gitignore
cat > ~/.gitk <<EOF
set mainfont {Monaco 10}
set textfont {Monaco 10}
set uifont {Monaco 10}
EOFI will know do some changes in the configuration to get the working on my mac. I understood that the best practice is to create a new branch.
git checkout -b localconfig HEADThis creates a new branch a switch in it immediatly.
I’ve modified some files into my local branch, and have commit to the localconfig branch.git add mymodifiedfile
git add ...
git commitgit commit -aNow I’ve seen that the other developer add update a lot of files in the trunk. So I will try to update my git branch.
git svn rebaseThis first revert your repository before my modifications update from subversion and apply again my commit. All went nicely. Notice that it is extremely more powerfull that trying to apply the update directly on the modified sources.
Now I want to commit to the remote svn, but the other developer don’t allow me to commit to the trunk. I will create a patch with git, create a new branch in the subversion repository from the trunk, apply the patch and then ask for the developer to merge changes from the new branch to the trunk.
So, let’s create the patchgit format-patch remotes/git-svnThen I create the branch into the subversion repository and checkout.
svn copy http://repos/trunch http://repos/branches/merge-branch
svn checkout http://repos/branches/merge-branch
cd merge-branchNow I need to apply the patch.
patch -p1 < /path/to/thepatchsvn commitNow I just have to send an email to the other developer.
With this first shot, I am conviced that git will improve my merging process and be a lot more flexible that SVN.
Now that I will play a lot with patches, next time I’ll probably take a look at StGIT (Stacked Git), patch management utility.
Rails : convert all tables to utf8 1
I sometimes need to convert old rails mysql databases to use unicode (utf8)
here is a way to do this quickly :
require 'rubygems'
require 'active_record'
db = "my_database"
sqlconn = ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "root",
:password => "",
:database => db
)
conn = ActiveRecord::Base.send(sqlconn.adapter_method,sqlconn.config)
conn.tables.each do |table|
q = "ALTER TABLE #{table} CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci"
puts q
conn.execute q
end
conn.execute("ALTER DATABASE #{db} DEFAULT CHARACTER SET utf8 ;")
edit : see Agouti’s comment
Enable backspace when ssh into a debian machine with zsh 2
As many users of mac OS X, I’ve encountered some troubles with the backspace key when ssh into a debian machine.
Reading some posts on the web, I was thinking that the problem was about the shell or the tty. But in fact it was related to zsh.
The default zsh map on debian is not correct for mac users. The solution is to tell zsh how to bind keys.
echo "bindkey ^? backward-delete-char" >> ~/.zshrc
echo "bindkey ^[[3~ delete-char" >> ~/.zshrcUse ctrl+v [key] to generate the ^... characters.
New syntax for DefaultOrder plugin 2
I’ve updated the DefaultOrder plugin that now have a new syntax.
class Contact < ActiveRecord::Base
order_by :fields => ['last_name', 'first_name'], :mode => :desc
end
Rails : Validate availablity of a distant ressource over HTTP
Sometimes you may host some ressources on a different website and you may want to validate the availability of it when creating a Rails model object (ActiveRecord::Base).
It would be dramatically unefficient to download the full media with a GET request. So, to achieve this we will use the HEAD http request that act as the GET request but return only the HTTP header without the body.
Here is a exemple of an ActiveRecord::Base object that validates the presence of the ressource among the Internet.
require 'net/http'
# the class is supposed to have a "media" attribute
# that is a relative url to a ressource hosted an a different
# website
class Article < ActiveRecord::Base
RESOURCE_HOST = "flickr.com"
RESOURCE_PORT = 80
validate :validates_presence_of_external_media
protected
def validates_presence_of_external_media
response = nil
# initiating the HTTP connection
Net::HTTP.start(RESOURCE_HOST, RESOURCE_PORT) do |http|
# doing the HEAD request
response = http.head(media)
end
# add an error if the request is not successful
errors.add :media, "ressource unavailable : #{response.code} #{response.msg}" unless
responce.kind_of?(Net::HTTPSuccess)
end
end
This is a very minimalist example, but this kind of technic may have a lot of uses.
Extract an image screenshot from a Video with ffmpeg 1
Here is a way to extract a sample image from a video with ffmpeg :
$ ffmpeg -itsoffset -4 -i sample.mov -vcodec png -vframes 1 -an -f rawvideo -s 320x240 test.png- -itsoffset -4 : means that you want to extract the image 4 seconds after video starts.
Default Order Plugin for Ruby On Rails
I’ve started the development of Default Order Plugin for Ruby on Rails
Easy setup a Mongrel cluster with Apache 2.2 on Mac OS X
Mongrel is a very fast and secure server for Ruby On Rails applications. It also supports Nitro and Camping. Setting up a mongrel_cluster on Mac OS X is not very difficult but it is a bit different from other Unix platforms.
What you need to start :Step 1 : Install Mongrel
Mongrel is available for unix platform and Win32 systems as a gem.
$ sudo gem install mongrel mongrel_clusterInstalling Apache 2.2
You can compile it from sources. But it is easier to install it via MacPorts.
$ sudo port install apache2All apache2 files will be installed in /opt/local/apache2, including binaries and configuration files.
Setting up Apache 2.2
chdir to /opt/local/apache2/conf and copy the sample file to httpd.conf$ cd /opt/local/apache2/conf
$ sudo cp httpd.conf.sample httpd.confCreate a new directory that will contain your application specific configuration files for Apache.
$ sudo mkdir myapp
$ cd myappCreate 3 files for your new application. (adapted from codahale blog)
$ sudo touch myapp.common myapp.conf myapp.cluster.confHere is the files content :
myapp.common :
ServerName www.myserver.com
DocumentRoot /path/to/my/app/public
<Directory "/path/to/my/app/public">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
RewriteEngine On
# Make sure people go to www.myapp.com, not myapp.com
RewriteCond %{HTTP_HOST} ^myapp.com$ [NC]
RewriteRule ^(.*)$ http://www.myapp.com$1 [R=301,L]
# Yes, I've read no-www.com, but my site already has much Google-Fu on
# www.blah.com. Feel free to comment this out.
# Uncomment for rewrite debugging
#RewriteLog logs/myapp_rewrite_log
#RewriteLogLevel 9
# Check for maintenance file and redirect all requests
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
# Deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
# Uncomment for deflate debugging
#DeflateFilterNote Input input_info
#DeflateFilterNote Output output_info
#DeflateFilterNote Ratio ratio_info
#LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
#CustomLog logs/myapp_deflate_log deflatemyapp.conf :
<VirtualHost *:80>
Include /opt/local/apache2/conf/myapp/myapp.common
ErrorLog /path/to/logs/error.log
CustomLog /path/to/logs/access.log combined
</VirtualHost>myapp.cluster.conf :
<Proxy balancer://mongrel_cluster>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
BalancerMember http://127.0.0.1:8002
</Proxy>Now that your files are created. at this to the bottom of /opt/local/apache2/conf/httpd.conf
NameVirtualHost *:80
Include conf/myapp/myapp.conf
Include conf/sites/myapp.cluster.confApache is now ready to run.
Setting up Mongrel cluster
Create a new dir for mongrel cluster config
mkdir /opt/local/etc/mongrel
cd /opt/local/etc/mongrelAnd create a new file “myapp.yml”
---
user: www
group: www
port: "8000"
cwd: /path/to/your/app/root
environment: production
address: 127.0.0.1
pid_file: log/mongrel.pid
servers: 3Setting up Startup Scripts
Enable apache startup script
$ sudo vi /etc/hostconfig
#add the following lines
APACHE2=-YES-
MONGREL=-YES-Copy the following into /Library/StartupItems/mongrel_cluster/mongrel_cluster
(adapted from original mongrel init script)#!/bin/bash
#
# Copyright (c) 2006 Bradley Taylor, bradley@railsmachine.com
#
# mongrel_cluster Startup script for Mongrel clusters.
#
# chkconfig: - 85 15
# description: mongrel_cluster manages multiple Mongrel processes for use \
# behind a load balancer.
#
[ -r "/etc/hostconfig" ] && . "/etc/hostconfig"
CONF_DIR="/opt/local/etc/mongrel"
RETVAL=0
ENABLE_FLAG=${MONGREL:=-NO-}
if [ "${ENABLE_FLAG}" = "-NO-" ]; then
echo "Mongrel is disabled. see /etc/hostconfig"
exit 0
fi
case "$1" in
start)
mongrel_cluster_ctl start -c $CONF_DIR
RETVAL=$?
;;
stop)
mongrel_cluster_ctl stop -c $CONF_DIR
RETVAL=$?
;;
restart)
mongrel_cluster_ctl restart -c $CONF_DIR
RETVAL=$?
;;
*)
echo "Usage: mongrel_cluster {start|stop|restart}"
exit 1
;;
esac
exit $RETVALLinux : ethernet interface supported media
I was just checking on my machines if all my ethernet cards supports 1Gb ethernet. On OS X ifconfig will give you what you want under the section supported media, but on Linux Debian it doesn’t. For this you have to use ethtool :
sudo ethtool eth0
