I’ve been playing around with Shoes (shoooes.net) lately as a way to put a cross-platform graphical user interface (GUI) on some of my small purpose-built command-line ruby scripts.
I find that it is quite easy to get started with, and lends a lot of flexibility to the way your program is structured and displayed. However, the structure feels a little bit alien compared to everyday ruby, and there are some gotcha’s you need to keep in mind while developing for Shoes.
I feel I must preface this article by saying that Shoes has excellent documentation, _why (the lucky stiff) turns documentation into its own art form. The manual, “Nobody Knows Shoes” reads a lot like a comic book, full of _why’s own original artwork and clippings from old-timey photos and art, and is complimented by the documentation at help.shoooes.net
I had a bit of trouble at first getting ActiveRecord to interface with a database from a straight port from one of my console apps because I glossed over the parts of the manual that detail the tricky behavior of the garbage collector reaping predefined classes after the app’s initial load.
The fix is pretty simple. Stick all your classes in an external file (or many) and load them using ‘require’.
Anyhow, here is a barebones example of a working implementation for using ActiveRecord in Shoes:
# in foo.rb class Foo < ActiveRecord::Base end #in app.rb Shoes.setup do gem 'activerecord' require 'active_record' ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :dbfile => 'foos_db.sqlite3' ) require 'foo' end Shoes.app do @foos = Foo.find(:all) para @foos end
Now, this example requires there is an existing sqlite database with a foos table, change out the establish_connection parameters to connect to any other database. The gem ‘activerecord’ statment tells shoes to install the activerecord gem into the shoes ruby library if it isn’t already there.
If you don’t already have a database, and just want to use a db to act as a storage layer for your app, then you might want to use ActiveRecord::Schema.define to create a database and setup the tables the same way you do for Rails migrations.
Here is a more complete example of an app to keep track of notes using ActiveRecord as the backend. I like the “base class that inherits from Shoes” pattern, so I’m using that here.
# in note.rb class Note < ActiveRecord::Base end # in app.rb Shoes.setup do gem 'activerecord' # install AR if not found require 'active_record' require 'fileutils' ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :dbfile => 'shoes_app.sqlite3' ) # create the db if not found unless File.exist?("shoes_app.sqlite3") ActiveRecord::Schema.define do create_table :notes do |t| t.column :message, :string end end end end class ShoesApp < Shoes require 'note' url '/', :index def index para 'Say something...' flow do @note = edit_line button 'OK' do Note.new(:message => @note.text).save @note.text = '' @result.replace get_notes end end @result = para get_notes end def get_notes messages = [] notes = Note.find(:all, :select => 'message') notes.each do |foo| messages << foo.message end out = messages.join("n") end end Shoes.app :title => 'Notes', :width => 260, :height => 350
There you are; a cross-platform desktop app that doesn’t require a full-on build environment, and can be distributed with the source exposed for later improvements.
The first time this runs, it installs Activerecord, requires it, establishes a connection, creates the table unless one already exists. Then it shows a form to add notes followed by all the existing notes in the database. Adding a new note refreshes the notes shown.
This isn’t exactly a polished app with full CRUD, but should prove a good introduction to Shoes for someone used to working with ActiveRecord.


Nice guide, man. Thanks!
PS – I submitted it to RubyFlow. I hope you don’t mind.
Definitely impressed. Glad to see some Shoes action going on, keep it up! :)
I have tried to run this an I get a “no driver for sqlite3 found” error.
I googled a bit and ended back here, so seem you are THE authority in the matter.
Can you give me some clue?
Is this common, or is it an issue of my installation?
Thank you in advance
@Fernando
Likely you don’t already have the sqlite gem installed. In the Shoes.setup block add a line that says “gem ‘sqlite3-ruby’”. That should do it. I overlooked that dependency because I already had Rails and its dependencies installed.
Thanks for this post it has been really helpful.
Just a note though, it took me some time to get this working on Mac OS X (Tiger) with the latest version of Shoes. It was complaining about not being able to find active_record. Even though I had it installed.
It turns out that it did not like requiring active_record in the setup block. So I just changed the setup block so it had
gem ‘activerecord’
I then put both require statements beneath the setup block. After that I moved the database setup stuff into the ShoesApp class at the top and all was working.
Hamza.
@Hamza Could you post a gist? Trying to get it running on Leopard, not sure where you put the establish_connection part
update: I got it running, but it gets stuck while trying to install the gem and eventually fails saying it could not find the gem, here’s the code: http://gist.github.com/90905
Hello,
First thank you for your post, I now know how to detect when a sqlite3 database was already created.
But would you know how to detect if a mysql database was already initialized by a ActiveRecord::Schema.define ?
I’m totally new to ruby and rails (I have just begun last night ^^), so excuse me if it is trivial…
@madprog
This should do the trick.
Very nice, thank you !