Thursday, June 14, 2012

My introduction to Passenger, nginx and Sinatra - "Not found"

I spent way too long getting passenger and nginx working with my Sinatra app.  My problem was, that I had set up a middleware class.  Instead of using the "top level" of the file to define the responses, I created a class deriving from Sinatra::Base.  So for example I had this for my webmain.rb:

require 'sinatra/base'

class MyApp < Sinatra::Base
   set :sessions, true
   set :foo, 'bar'

   get '/' do
      'Hello world!'
   end
end

This worked fine when running the application with the rackup command, but in passenger, it just said "not found".  Not a very helpful error message at all.  There was nothing else on the page (if nginx has an error, it says 'nginx' centred on the page.), so apparently the problem was in sinatra.  This is the config.ru file that I had:

require 'rubygems'
require 'sinatra'
require File.join(File.dirname(__FILE__), 'webmain.rb')


run Sinatra::Application

Can you see what's wrong?  I couldn't either.  Apparently no-one else had been dense enough to have this problem on stack overflow or anywhere else I could find with google.  After trying different config.ru files and using strace on the nginx and passenger processes, I gave up for the night.

The next evening after getting home from work, I came to a realisation.  I changed the config.ru file to this:

require 'rubygems'
require 'sinatra'
root_dir = File.dirname(__FILE__)
require File.join(root_dir, 'webmain.rb')

run MyApp
I needed to actually run the class I created. Success!

Note that the File.join stuff is needed because I'm using ruby 1.9, which uses relative paths for "require"s that aren't in the installed directories.

Versions of the software I'm using:

Passenger: 3.0.12
Sinatra: 1.3.2
ruby: 1.9.3p0


Wednesday, June 13, 2012

The rvm sudo gem install gotcha

The title of the post says it all.  Ruby Version Manager (RVM) is handy for quickly switching between different versions of ruby, but if you have been using a system installation, your muscle memory may have you typing this to install a gem:
sudo gem install

It doesn't work as you might expect with rvm. It installs the gem in the gem repository of the system ruby.

I got caught out by this, and I hope others can learn from my mistakes.

So if you have done:

rvm use 1.9.2

Then to install a gem, you should go

gem install


Saturday, June 9, 2012

BrowserID with Ruby and Sinatra

I have been playing with Mozilla's browserid (soon to be called Mozilla Persona), which is a service to manage authentication with your email address as the login. I am using the ruby gem called sinatra/browserid to access it. When moving my code to a new computer, I started getting these errors:
application error TypeError at /_browserid_assert can't convert nil into String file: common.rb location: initialize line: 148
It seems to be a problem with a change in ruby 1.9.3 http.post which returns a single res instead of a res, body pair. I found a fork of the gem that fixes this problem. These are the commands to install the forked gem from github:
git clone https://github.com/passcod/sinatra-browserid.git gem build sinatra-browserid.gemspec sudo gem install sinatra-browserid-0.3.1.gem
(omit the sudo if you use rvm).

Monday, June 13, 2011

Using the nustache template engine.

Nustache is Mustache for .net. Get it from https://github.com/jdiamond/Nustache

Here is a basic example in c#.
string sTemplate = "* {{greeting}} {{subject}}!";
Dictionary<string, string> testData = new Dictionary<string,string>();
testData["greeting"] = "Hello";
testData["subject"] = "world";
Console.Out.WriteLine(Nustache.Core.Render.StringToString(sTemplate, testData));
The Render class has different methods for different inputs and outputs, such as FileToFile and FileToString.

This is the output produced:
* Hello world!

Friday, October 15, 2010

Upgrading a linode from an old version of ubuntu (8.10 Intrepid)

I was trying to upgrade my linode today, and I had one issue. I thought I'd share it for anyone else who got this error message on Ubuntu 8.10 Intrepid.

I read the linode library article about upgrading to 10.10, and for the most part it was applicable, but the advice to use the "Latest 2.6 Paravirt" kernel caused problems on 8.10. If I had left it alone, this problem wouldn't have happened.

When I switched over to that kernel and rebooted, my networking from within the linode to the outside world had stopped working. I didn't realise this immediately, because the websites were still working and I was able to ssl into the linode.

When I ran

do-release-upgrade -d


I got the following message:

no new release found


Simply switching the linode back to use the current stable version allowed me to upgrade to 9.04. From there on, the paravirt kernel worked fine.

By the way, switching kernels is done by clicking on the configuration profile on the dashboard of your linode.

Friday, May 29, 2009

Google Wave - Why HTML5?

I have been caught up in the hype of google wave. I'll assume you already know what google wave is (Think of it as a mix of instant messaging with email). After watching the Google I/O presentation video, I was thinking, why does this have to be implemented in html 5? Here are some reasons I can dream up:

  1. Html 5 is a richer markup language, with new elements supporting web apps, not least of which is native support for video and other media. It has better support for web apps, including the well known canvas.
  2. Html5 is still in development, so the developers of wave can suggest new features that would be useful for their application. At about 16minutes into the video they mention that they are working on a proposal to get a feature added into html5. The wave team had one feature that they want html 5 to support, which is dragging and dropping files from the local machine into the browser. Currently they use google gears to provide this functionality.
  3. The local storage feature of html5 enables the use of more data in a single web app. So even though there can be a lot of information in each wave, the wave can be brought up instantaneously, and the user can scroll through the history of the messages for a single wave, and the app is still highly responsive. (I am assuming this was done using local storage, otherwise I can't imagine xml and media over the network would be as fast as I saw.
  4. The next version of Internet Explorer (8) does not have full support for html5. Even though the google guys say they are happy that Microsoft will support html5 in the future, this will not happen immediately, and IE will lose market share if google wave really takes off.
  5. This is the main one for me. Google believes that html5 is the future of the web. Google doesn't have to create their own OS, because html5 is going to be the next operating system of the web. With html5 there is no need for flash, no need for silverlight, or a particular browser. Google can continue doing what they do best, which (after search and advertising) is build web apps using raw html and javascript.

Some of these reasons are more side-effects than causes. Either way, with google wave, html 5 has become a much more important language for web developers, and for me Wave has brought html5 very much from a working draft, into the near future.

Thursday, May 21, 2009

ActiveRecord Oracle Enhanced adapter with legacy tables - primary key triggers.

I was using active record, Inserting data into tables that have triggers set up to create the primary key from a sequence of numbers. The oracle adapter doesn't support this 'out of the box'.

When I read about the approach that the oracle adapter takes to auto incrementing primary keys, my first thought was that it was a bad idea. Why wouldn't you use the 'standard' approach of creating a sequence for the primary key, and writing a trigger to set the primary to the next value of the sequence upon creation of a record? This ensures that the same policy is used, whether a stored procedure or an ad-hoc insert is used. (I am talking about the fact that the oracle adapter creates its own primary key using #next_sequence_value in oracle_enhanced_adapter.rb.)

It's probably just me; I am coming from the viewpoint of someone who has spent the last 3 years working with oracle databases using plsql stored procedures to program much of the logic. I already have the sequences (which ActiveRecord migrations create automatically). I also have triggers, which interfere with the adapters behaviour.

To someone who just wants to move their rails application onto an oracle database, the approach taken by the adapter makes more sense. Also no oracle-specific code (outside of the adapter itself) has to be used.

I can imagine an adapter for data definition commands (eg table creation), encapsulating this code, but as far as I know, rails migrations are fairly basic when it comes to setting up a database. They require extra setup for foreign keys, for example.

I tried searching for a solution in the blogosphere, this post mentions this problem, but is actually about an issue with LOBs, which is solved in a later version.

Raimonds Simanovskis, the maintainer of the adapter, blogged about custom activerecord methods for legacy oracle databases.
It didn't help, because my knowledge of how activerecord adapters work was pretty limited at the time. (It is only slightly less limited now).

I posted to the "oracle-enhanced" google group and Raimonds was kind enough to improvise an 'ugly' solution. I tried it out and it seemed to work.

I added the code to the end of the apps config/environment.rb:
class ActiveRecord::Base
set_create_method do    
quoted_attributes = attributes_with_quotes
conn = connection.raw_connection
cursor = conn.parse <<-EOS
BEGIN
INSERT INTO #{self.class.quoted_table_name} (#{quoted_column_names.join(', ')}) 
VALUES(#{quoted_attributes.values.join(', ')})
RETURNING #{self.class.primary_key} INTO :id;
END;
EOS
cursor.bind_param(':id', nil, Integer)
cursor.exec
id = cursor[':id']
cursor.close
id
end
end

What does this code do? It replaces the default active record create method with a method that sends a small pl/sql
script (the bit between BEGIN and END) which gets the new primary key. Note this works even if you change the name of
the primary key in your model using set_primary_key.

This also requires the plsql gem to be installed, which seems to be required for the adapter anyway.

There is one major shortcoming; this patch causes inserts to only work with tables that have an auto-increment sequence and trigger combination set up.

Ideally, this code could be incorporated into the adapter, and a setting could be used to switch it on or off. I don't know if there would be much demand for it, though.