A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Friday, February 4, 2011

Running a Ruby 1.9 Sinatra app on Heroku

I just got my first significant application running on Heroku. It uses Sinatra instead of Rails and uses Ruby 1.9 - as a result the steps to get the application up and running were slightly different from the Heroku Quickstart Guide, which is tailored towards Rails apps.

1. Setup
Setup a Heroku account and set up the SSH keys
Create your app and make sure it runs correctly on your local machine.
Make sure that all paths are relative to the application root.
Run the Sinatra app from a config.ru file.

2. Setup Bundler
I had an issue with this originally but this is what worked. I only need the sinatra gem so my Gemfile is:
source :gemcutter
gem 'sinatra'
and my config.ru file is:
require 'bundler'
Bundler.require
require 'sinatra'
require './my_app.rb'
run MyApp.new
Note that although you need to have the heroku gem installed on your system in order to upload to Heroku, you do not 'require' it in your app.

3. Setup git and commit the project.

4. Create the Heroku app
You want to specify an application name, otherwise Heroku will give you an arbitrary one. You also want to specify the run environment at Heroku that will be used. They refer to this as the 'stack' and for Ruby 1.9 you want to specify this directly and currently the correct option is 'bamboo-mri-1.9.2'. The create command is:
$ heroku create my_app_name --stack bamboo-mri-1.9.2

5. Push the git repository to Heroku with:
$ git push heroku master
The messages that follow should look something like this (some lines removed):
-----> Heroku receiving push
-----> Sinatra app detected
-----> Gemfile detected, running Bundler version 1.0.7
Unresolved dependencies detected; Installing...
Fetching source index for http://rubygems.org/
Installing rack (1.2.1)
Installing tilt (1.2.2)
Installing sinatra (1.1.2)
Using bundler (1.0.7)
Your bundle is complete! It was installed into ./.bundle/gems/
Compiled slug size is 500K
-----> Launching... done
http://my_app_name.heroku.com deployed to Heroku
Now go to that URL and your app should be running.

If there was a problem and the app failed to start then look at the logs:
$ heroku logs -n 100


You can set up apps with minimal (or no) database storage for free on Heroku. This is a great service as it lets you experiment to your heart's content.

The idea behind Heroku is to remove from you the burden of server configuration. For my simple application this seems to work remarkably well.



 

Tuesday, February 1, 2011

Ruby 1.9 and incompatible character encodings

I run into issues pulling remote text data into a Ruby 1.9 / Rails 3 app, which is using utf-8 encoding by default. The problem apparently comes from non-Ascii characters in binary or so-called ASCII-8BIT encoded text. I don't have a proper way to translate the offending characters as yet but my workaround is to strip them out and/or replace them with an ASCII character.

This regex implements the workaround. Be sure to use the 'n' modifier on the regex. This specifies that the encoding of the text should be ignored and thus multibyte characters are treated as separate bytes.
    str.gsub!(/[^\x00-\x7F]/n,'?')

Far from perfect, but it gets the job for me right now.

 

Tuesday, January 4, 2011

rvm and shell scripts

If you want to use a specific version of Ruby via RVM inside a shell script then you need to make sure that the environment is setup correctly.

The RVM site addresses that HERE for the case where RVM is installed in a user's home directory.

But on my server I have a system-wide installation. In that case you should have a /etc/rvmrc file with a default setup and you need to source this.

Your scripts should look something like this:
#!/bin/bash                                                                                                                                                 
source "/etc/rvmrc"

rvm use 1.9.2

# mycommands_go_here


 

Tuesday, December 21, 2010

Per Page Inclusion of JavaScript in Rails view pages

I use various jQuery plugins in my Rails views but I don't want to download all that code in pages that don't use them. Furthermore I want to minimize the chance of namespace conflicts between different blocks of code.

A simple way to do this is to add these lines to your application.html.erb file after the main JS includes:
<%= yield :custom_javascript_includes %>
and then add a block similar to this in each view template that needs custom JS.
<% content_for :custom_javascript_includes do %>
<%= javascript_include_tag "your_custom_plugin.js" %>
<script type="text/javascript">
// Your custom JavaScript code
</script>
<% end %>
In this example I'm including a specific file from the public/javascripts directory and then adding some custom JS code that might define some events or trigger some action on page load.

Here is a real example that uses the facebox jQuery plugin which provides 'light box' functionality. This code is placed at the top of my 'show' template.
<% content_for :custom_javascript_includes do %>
<%= javascript_include_tag "facebox.js" %>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('a[rel*=facebox]').facebox({
loadingImage : '/images/facebox_loading.gif',
closeImage : '/images/facebox_closelabel.gif'
});
});
</script>
<% end %>
You can take this further by also including custom stylesheets linked to these plugins in the same block. That can result CSS and JS includes being interspersed in the resulting HTML file which some people may not like, but I don't think there are any practical drawbacks to it.

The big win is that you keep your custom JS code right there in the same file as your HTML. If that JS code is substantial you could move it into a partial that resides in your views directory, as opposed to having it separated in the public/javascripts directory.

For high performance production sites you should weigh the benefits of this approach in terms of clarity with the performance benefit of stashing all your JS code in a single file and minifying it.


 

Tuesday, December 14, 2010

MySQL Data export/import probelm with SQL SECURITY DEFINER

Importing a MySQL database dump from a client into my system I got this error:
$ mysql -u root -p  example_db < example_db_dump.sql 
Enter password:
ERROR 1449 (HY000) at line 5172: The user specified as a definer ('smith'@'localhost') does not exist
Running 'grep' for that user turned up a bunch of lines like this:
/*!50013 DEFINER=`smith`@`localhost` SQL SECURITY DEFINER */
These are created on the 'donor' MySQL system when creating one or more views of the data. That user does not exist on my system and so MySQL complains.

I don't care about those views so the easiest way to deal with this issue is to remove these '50013' lines. You can do that with 'sed':
$ sed '/\*\!50013 DEFINER/d' example_db_dump.sql > example_db_dump_clean.sql
You need to drop the new database as the import process partially worked, re-create it and then you can reimport:
$ mysqladmin -u root -p drop example_db
$ mysqladmin -u root -p create example_db
$ mysql -u root -p example_db < example_db_dump_clean.sql


Now, if you need to use the Views in your copy of the database then you need to either create that user locally and leave the lines, or change the user in those lines to one that does exist locally.

 

Sunday, December 12, 2010

Installing Amazon EC2 tools on Ubuntu 10.04

The Amazon EC2 ami and api tool packages are not found by apt-get using the default sources list. You need to add 'multiverse' to the list. Here is how you install the tools:
$ sudo perl -pi -e 's%(universe)$%$1 multiverse%'  /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get install ec2-ami-tools
Of course, you also need to set up your environment variables as per usual so that the tools can access your keys.

 

Sunday, December 5, 2010

Using Bundler with a non-Rails Ruby project

Bundler is a Ruby Gem to help you manage the various gem dependencies in your application.

It has gotten a lot of attention as it is ,er, bundled with Rails3 and represents a welcome addition to that framework. But you can use Bundler in any Ruby application to help make deployments go smoothly.

For a regular Ruby application the steps involved are simple:

1: Install Bundler on your system
$ gem install bundler
2: Create a file called 'GemFile' at the top level of your application directory
Add gem sources to this and each gem that your application relies on. This example includes the main gem sources and a single gem
source :rubygems
source :rubyforge
source :gemcutter

gem "json"
3: Run 'bundle install'
This will now install any missing gems. It does harm to run it more than once.
$ bundle install
Fetching source index for http://rubygems.org/
Fetching source index for http://rubygems.org/
Fetching source index for http://rubygems.org/
Using json (1.4.6)
Using bundler (1.0.3)
Your bundle is complete! It was installed into /Users/jones/.rvm/gems/ruby-1.9.2-p0
If you look in your application directory you will see a new file called Gemfile.lock. Bundler uses this and you want to keep it, adding it to your git repository (or equivalent). You can also find a .bundle directory containing a config file. I guess you can use this for fancier configurations, but a basic app you can ignore it.

4: Deploy your app
Now when you deploy your app in a new location (with the bundler gem installed) you can simply run 'bundle install' in your app directory and you'll be good to go.


 

Archive of Tips