{"id":27,"date":"2008-11-18T22:09:53","date_gmt":"2008-11-19T03:09:53","guid":{"rendered":"http:\/\/unixmonkey.net\/?p=27"},"modified":"2008-11-18T22:09:53","modified_gmt":"2008-11-19T03:09:53","slug":"ive-got-some-activerecord-in-my-shoes","status":"publish","type":"post","link":"https:\/\/unixmonkey.net\/?p=27","title":{"rendered":"I&#8217;ve got some ActiveRecord in my Shoes"},"content":{"rendered":"<p>I&#8217;ve been playing around with Shoes (<a href=\"http:\/\/shoooes.net\">shoooes.net<\/a>) lately as a way to put a cross-platform graphical user interface (GUI) on some of my small purpose-built command-line ruby scripts.<\/p>\n<p>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.\u00a0However, the structure feels a little bit alien compared to everyday ruby, and there are some gotcha&#8217;s you need to keep in mind while developing for Shoes.<\/p>\n<p>I feel I must preface this article by saying that Shoes has excellent documentation, <a href=\"http:\/\/twitter.com\/_why\">_why (the lucky stiff)<\/a> turns documentation into its own art form.  The manual, <a href=\"http:\/\/hackety.org\/press\/\">&#8220;Nobody Knows Shoes&#8221;<\/a> reads a lot like a comic book, full of _why&#8217;s own original artwork and clippings from old-timey photos and art, and is complimented by the documentation at <a href=\"http:\/\/help.shoooes.net\">help.shoooes.net<\/a><\/p>\n<p>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&#8217;s initial load.<\/p>\n<p>The fix is pretty simple. Stick all your classes in an external file (or many) and load them using &#8216;require&#8217;.<\/p>\n<p>Anyhow, here is a barebones example of a working implementation for using ActiveRecord in Shoes:<\/p>\n<pre lang=\"ruby\">\n# in foo.rb\nclass Foo < ActiveRecord::Base\nend\n\n#in app.rb\nShoes.setup do\n  gem 'activerecord'\n  require 'active_record'\n  ActiveRecord::Base.establish_connection(\n    :adapter   => 'sqlite3',\n    :dbfile    => 'foos_db.sqlite3'\n  )\n  require 'foo'\nend\nShoes.app do\n  @foos = Foo.find(:all)\n  para @foos\nend\n<\/pre>\n<p>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 &#8216;activerecord&#8217; statment tells shoes to install the activerecord gem into the shoes ruby library if it isn&#8217;t already there.<\/p>\n<p>If you don&#8217;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.<\/p>\n<p>Here is a more complete example of an app to keep track of notes using ActiveRecord as the backend.  I like the &#8220;base class that inherits from Shoes&#8221; pattern, so I&#8217;m using that here.<\/p>\n<pre lang=\"ruby\">\n# in note.rb\nclass Note < ActiveRecord::Base\nend\n\n# in app.rb\nShoes.setup do\n  gem 'activerecord' # install AR if not found\n  \n  require 'active_record'\n  require 'fileutils'\n\n  ActiveRecord::Base.establish_connection(\n    :adapter   => 'sqlite3',\n    :dbfile    => 'shoes_app.sqlite3'\n  )\n\n  # create the db if not found\n  unless File.exist?(\"shoes_app.sqlite3\")\n    ActiveRecord::Schema.define do\n      create_table :notes do |t|\n        t.column :message, :string\n      end\n    end\n  end\n\nend\n\nclass ShoesApp < Shoes\n  require 'note'\n\n  url '\/', :index\n \n  def index\n    para 'Say something...'\n    flow do\n      @note = edit_line\n      button 'OK' do\n        Note.new(:message => @note.text).save\n        @note.text = ''\n        @result.replace get_notes  \n      end\n    end\n    @result = para get_notes\n  end\n  \n  def get_notes\n    messages = []\n    notes = Note.find(:all, :select => 'message')\n    notes.each do |foo|\n      messages << foo.message\n    end\n    out = messages.join(\"n\")\n  end\n\nend\n\nShoes.app :title => 'Notes', :width => 260, :height => 350\n<\/pre>\n<p>Here&#8217;s a screenshot:<br \/>\n<a href='https:\/\/unixmonkey.net\/blog\/wp-content\/uploads\/2008\/11\/notes.gif'><img decoding=\"async\" src=\"https:\/\/unixmonkey.net\/blog\/wp-content\/uploads\/2008\/11\/notes.gif\" alt=\"notes, the Shoes app\" title=\"notes\" class=\"alignnone size-full wp-image-28\" \/><\/a><\/p>\n<p>There you are; a cross-platform desktop app that doesn&#8217;t require a full-on build environment, and can be distributed with the source exposed for later improvements.<\/p>\n<p>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.<\/p>\n<p>This isn&#8217;t exactly a polished app with full CRUD, but should prove a good introduction to Shoes for someone used to working with ActiveRecord.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;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.\u00a0However, the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,14,17,1],"tags":[35,36,32],"_links":{"self":[{"href":"https:\/\/unixmonkey.net\/index.php?rest_route=\/wp\/v2\/posts\/27"}],"collection":[{"href":"https:\/\/unixmonkey.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unixmonkey.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unixmonkey.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unixmonkey.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=27"}],"version-history":[{"count":0,"href":"https:\/\/unixmonkey.net\/index.php?rest_route=\/wp\/v2\/posts\/27\/revisions"}],"wp:attachment":[{"href":"https:\/\/unixmonkey.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unixmonkey.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unixmonkey.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}