Sooner or later every new Ruby developer needs to understand differences between this two common rake tasks. Basically, these simple definition tells us everything we need to know:

  • rake db:migrate runs migrations that have not run yet
  • rake db:schema:load loads the schema.db file into database.

but the real question is when to use one or the other.

Advice: when you are adding a new migration to an existing app then you need to run rake db:migrate, but when you join to existing application (especially some old application), or when you drop your applications database and you need to create it again, always run rake db:schema:load to load schema.

Example

I am working on application which use globalize gem for ActiveRecord model/data translations. Globalize work this way:

  • first specify attributes which need to be translatable
1
2
3
class Post < ActiveRecord::Base
  translates :title, :text
end

If you use Vagrant, VirtualBox and Ubuntu to build your Rails apps and you want to test it with Cucumber scenarios, this is the right post for you. By default Vagrant and VirtualBox use Ubuntu without an X server and GUI.

Everything goes well until you need @javascript flag for your cucumber scenario. @javascript uses a javascript-aware system to process web requests (e.g. Selenium) instead of the default (non-javascript-aware) webrat browser.

Install Mozilla Firefox

Selenium WebDriver is flexible and lets you run selenium headless in servers with no display. But in order to run, Selenium needs to launch a browser. If there is no display to the machine, the browsers are not launched. So in order to use selenium, you need to fake a display and let selenium and the browser think they are running in a machine with a display.

Install latest version of Mozilla Firefox:

sudo apt-get install firefox

Since Ubuntu is running without a X server Selenium cannot start Firefox because it requires an X server.

Setting up virtual X server

Virtual X server is required to make browsers run normally by making them believe there is a display available, although it doesn’t create any visible windows.

Another simple task that’s often hard for beginners is importing and exporting MySQL dumps. Here is quick rundown on how to do it.

To export data you need to use mysqldump:

1
mysqldump -u db_user -p db_name > dump_name.sql

Options given to mysqldump are:

  • -u db_user – connect as user db_user to database
  • -p – use password, it will ask you to enter your password
  • db_name is the name of MySQL database you want to dump
  • > dump_name.sql – by default mysqldump will print out the dump to terminal, but simple output redirect with > will instead write it to given filename, in this case dump_name.sql

Now that you have dump_name.sql file with all SQL queries needed to replicate your database you can import it using general-purpose mysql client:

1
mysql -u db_user -p db_name < dump_name.sql

User, password, and database name options are the same as for mysqldump. Since mysql reads input from terminal this time we can use < to read input from given file instead.

As always for more information you can consult manual using man mysqldump and man mysql.

One of the simplest tasks is creating and extracting files using tar and gzip. Yet for most new developers this is a daunting task. These days tar is mostly used to simply combine a few files into a single file and then gzip is used to compress that file.

Here is a quick overview how to use tar and gzip to create and compress an archive:

1
2
3
4
5
6
7
8
# archive individual files
tar -cvzf myarchive.tar.gz /path/to/file1 /path/to/file2

# archive whole directory
tar -cvzf myarchive.tar.gz /path/to/dir

# archive whole directory but don't store full path
tar -cvzf myarchive.tar.gz -C /path/to/dir ./

Options give to tar are: c to create new archive, v to be verbose, z to compress resulting archive with gzip, and f to write the archive to specified file. After options you can list files and dirs you want to archive.

In all examples we provide a full path to a file or dir we want to archive. In this case tar will store files in the archive using the full path. This means once you extract the files you’ll have a complete directory structure from root dir onwards.

The way to avoid this is either to manually cd to dir in which files are stored, or to tell tar using C option to change dir before archiving files.

Finally to extract an archive:

1
tar -xvzf myarchive.tar.gz

The x option tells tar to extract the archive into current directory.

For more information you can consult manual using man tar.

A gem is a simple way to distribute functionality, it can be a small plugin, a Ruby library or sometimes a whole program. Thanks to RubyGems, a gem hosting service, developers have a wide range of gems at their disposal allowing them to easily add functionality to their applications.

But what if there is no gem available that will suit the functionality you need, and you find yourself writing the same code over and over again for different projects? Well, in that case you should consider making your own gem.

It’s considered a good practice to extract a gem out of an existing application, since that way you will have a better understanding of all the requirements as well as how the gem will be used. This blog post will illustrate just that on a real life example, and will take you through the process of creating a slug_converter gem.

For our new project it was necessary to modify the starting id of our database. This can be handled through migration for creating table but we decided to create a rake task that handled this for us.

The rake task that we created detects what database is being used and executes appropriate changes according to that.

If you are using Devise gem for authentication and you have been adding custom fields to your model you’ll get in trouble when you try to create a new instance or update an existing one. All your added fields will be treated as unpermitted. The solution for this problem is to customise Devise’s configure_permited_parameters action. All you need to do is to add this action to your Application controller and push parameters that need to be permitted to devise_paremeter_sanitizer array. So let’s say you have a User Model and you have added company_name and website fields to your user’s table, to permit this parameters on sign_up you need to add this to your Application controller:

1
2
3
def configure_permitted_parameters
  devise_parameter_sanitizer.for(:sign_up).push(:company_name, :website)
end

It is the same principle for the :sign_in and :edit_account. You can see what are default permitted parameters here.

Devise has a very useful Trackable module used to track user’s sign in count, timestamps and IP address. There are some occasions when you need to disable tracking. For example for API requests where user signs in on every request; for instances where admin might sign in as an user; and similar.

To disable Devise Trackable module you need to set request.env["devise.skip_trackable"] = true. You have to do that before trying to authenticate user, so you’ll want to put it in a before_filter, or even better prepend_before_filter to make sure it’s before authentication.

Add this to your controller in which you want to disable tracking:

1
2
3
4
5
6
prepend_before_filter :disable_devise_trackable

protected
  def disable_devise_trackable
    request.env["devise.skip_trackable"] = true
  end

Note to self: here is how to upgrade Ubuntu 8.04 LTS (or any other release that is no longer supported) to newer Ubuntu release.

When you are upgrading unsupported release of Ubuntu if you try to do the usual sudo apt-get update it will most likely fail because… well, it’s unsupported. The simple fix for this is to change your /etc/apt/sources.list and replace repository URLs from something like us.archive.ubuntu.com to old-releases.ubuntu.com.

After that you should be able follow normal upgrade procedure (use sudo if you are not root):

1
2
3
apt-get update
apt-get install update-manager-core
do-release-upgrade

References:

Here is a quick way to setup VirtualBox using Vagrant with Heroku-like box on Mac.

  1. Install VirtualBox from https://www.virtualbox.org/wiki/Downloads

  2. Install Vagrant from http://downloads.vagrantup.com/

  3. Create Vagrantfile for Heroku-like box (based on https://github.com/ejholmes/vagrant-heroku) that looks something like:

1
2
3
4
5
6
    Vagrant.configure("2") do |config|
        config.vm.box = "heroku"
        config.vm.box_url = "https://dl.dropboxusercontent.com/s/rnc0p8zl91borei/heroku.box"
      config.vm.synced_folder ".", "/vagrant", :nfs => true
        config.vm.network :private_network, ip: "192.168.1.42"  # required for NFS
    end

Beside telling Vagrant to use Heroku-like box from https://github.com/ejholmes/vagrant-heroku it also sets up shared dir between host and VM machine. It will mount Vagrantfile dir (.) to /vagrant in VM.

vagrant up will setup the VM and start it up.

Now you can use vagrant ssh to login to VM.

Vagrant Heroku-like box comes with Postgresql, but if you want you can easily setup sqlite:

1
sudo apt-get install libsqlite3-dev

Bonus tip: when you are working on multiple projects sometimes you can forget which VMs are running. You can list all running VMs using:

1
VBoxManage list runningvms

Further reading: