Subscribe to the MPC blog rss feed feed-icon-14x14
 

Using Shoes To Write A Platform Independent Desktop Client

Posted on 04:42AM on 09/27/2008
Tags: ruby, shoes

Lately I've been looking for ways to track my billable time. I stumbled upon Slim Timer a while back and the more I play with it, the more I like using it. Thanks to Richard White for making it available.

One small problem I have with it, though, is that I don't enjoy using a web interface for tracking my time. I don't know why, it just seems to break my workflow. According to the site, there is a Windows client called Bubbles that can be used; however, I run Linux, not Windows, so that option is out.

I had some free time, so I got to thinking about how I could easily write a desktop application that would run on a variety of platforms to interact with the Slim Timer API. My first thought was a Java Swing client, but that seemed inelegant.

Then I remembered Shoes. I had heard about Shoes a while back on Ruby Inside, but had not given it much thought.

On further investigation, though, it seemed like Shoes might be a good solution. A Shoes application is written using Ruby and can be compiled to run in Linux, Mac OS, and Windows. This is great in my opinion since I like Ruby and you never know when someone else on a different platform might be able to use the application

Another really cool feature of Shoes it that although you create desktop applications with it, in many ways it's a lot like creating a web application. Shoes has the concept of links that point to within (or without) the application. Shoes also has the concept of styles. Using styles is similar to styling HTML.

So far I've build a prototype of my Slim Timer On Shoes that works on Windows, Mac and Linux. It will likely take some time since I need to learn more about Shoes as I go!

Here's a very simple example of a Shoes application:

#SlimTimerOnShoes.rb
Shoes.setup do
  gem 'slimtimer4r'
end
$:.push(File.join(File.dirname(__FILE__), "lib"))

#loads a variety of additional helper classes - not shown
require 'loader'

class SlimTimerOnShoes < Shoes
 
  #'urls' within the application
  url '/', :index
  url '/task/new', :create_task
  url '/task/stop/(\\d+)', :stop_task
  url '/task/complete/(\\d+)', :complete_task
  url '/task/show/(\\d+)', :show_task
  
  @@actions = {
    :main => MainAction.new,
    :show => ShowAction.new,
    :configure => ConfigureAction.new,
    :complete => CompleteAction.new,
    :start => StartAction.new,
    :stop => StopAction.new,
    :create => CreateAction.new
  }
  
  def index
    Settings.configured? ? show_index : configure
  end
  
  def show_index
    run_action(:main)
  end
  
  def configure
    LoggerFacade.log("Application not configured. Bringing up configuration screen.", LoggerFacade::INFO)
    run_action(:configure)
  end
  
  def complete_task(task_id)
    run_action(:complete, task_id)
  end
  
  def start_task(task)
    run_action(:start, task)
  end
  
  def stop_task(task_id)
    run_action(:stop, task_id)
  end
  
  def create_task
    run_action(:create)
  end
  
  def show_task(task_id)
    run_action(:show, task_id)
  end
  
  private
  
  def run_action(action, *args)
    a = @@actions[action]
    a.app = self
    a.execute(*args)
  end
  
end

Shoes.app :title => "SlimTimer On Shoes", :width => 500, :height => 500, :resizable => true

2 Comments (Show) (Comments are closed for this post)

named_scope

Posted on 03:45AM on 09/21/2008
Tags: activerecord, ruby, rails

Lately everyone has been going mad over a relatively new addition to rails: named_scope. Up until now, I hadn't had the chance to try it out. I always just assumed that it was more syntactic fluff that seems to accumulate. Wow, was I wrong! It's an unbelievably cool and useful idea. Here's a really simple example. Say I have 2 models: Country and Region. They are as you would expect. A Region belongs to a Country and a Country has many Regions, etc. I use them pretty much for dropdown lists and things like that. Here's some code:

class Region < ActiveRecord::Base
  belongs_to :country
end

class Country < ActiveRecord::Base
  has_many :regions
end

Prior to named_scope, if you wanted to get all Regions in alphabetical order (as an example), you'd have to do something like:

class Region < ActiveRecord::Base
  #other code
  def self.ordered
    find(:all, :order => "name ASC")
  end
end

Which was ok, but this is nicer:

class Region < ActiveRecord::Base
  named_scope :ordered, :order => "name ASC"
  #other code
end

This creates a method on the Region class called ordered that can simply be called.

OK, so that's cool and all, but really not that big a deal, right? Well, no - until you consider that you can chain calls to named_scope, thus adding more and more constraints. For example:

class Region < ActiveRecord::Base
  belongs_to :country
  named_scope :ordered, :order => "name ASC"
  named_scope :by_country, lambda { |c| { :conditions => ["country_id = ?", c.id] } }
  named_scope :containing, lambda { |s| { :conditions => ["name like ?", "%#{s}%"] } }
end

class Runner
 c = Country.find_by_name("Canada")
 regions = Region.by_country(c).containing("A").ordered
 puts "Provinces in Canada containing the letter A in ascending order: #{regions.inspect}"
end

This generates SQL that looks like this:

SELECT * FROM `regions` WHERE ((name like '%A%') AND (country_id = 1)) ORDER BY name ASC

Another reason that I like name_scope is that because models such as these are frequently eused in dropdowns, etc, you can use named scope to return a very lightweight version of the class, while excluding attributes that are unnecessary for a simple dropdown. For example:

class Region < ActiveRecord::Base
  belongs_to :country
  named_scope :ordered, :order => "name ASC"
  named_scope :by_country, lambda { |c| { :conditions => ["country_id = ?", c.id] } }
  named_scope :containing, lambda { |s| { :conditions => ["name like ?", "%#{s}%"] } }
  named_scope :simple, :select => "id, name"
end

This allows me to only bring back the attributes that I need. And again, it could be chained with other named scopes

I think that this is a very powerful concept that allows developers to write more DRY and readable code.

0 Comments (Show) (Comments are closed for this post)

Interesting Time Tracking site

Posted on 03:50AM on 09/16/2008
Tags: freelance, tools

SlimTimer looks like an interesting web application. Build using Ruby on Rails, it allows you to create tasks and time them. Then you can report on them, etc. Could be quite useful for the freelancer.

0 Comments (Show) (Comments are closed for this post)

Searching Enabled!

Posted on 09:14PM on 09/13/2008
Tags: search, blog

As per my last post, I've decided to turn on fulltext indexing on post columns within MySQL. This seems like the lowest overhead solution and appears to work well.

0 Comments (Show) (Comments are closed for this post)

Full Text Search

Posted on 04:12PM on 09/12/2008
Tags: search, rails, python, ruby, django, sinatra

I've come up with my next chunk of functionality that I'd like to implement for this site - full text searching on blog posts. There appear to be several options:

UPDATED: I could also use MySQL fulltext indexes and just search those if I wanted to make it really easy ;)

I don't want anything complicated and I'd rather not add any big additional overhead to my already low on resources slice, so I'm leaning towards acts_as_indexed.

I realize that there'll be some work involved regardless since I'm not using ActiveRecord here and all of these plugins assume Rails.

Additionally, I'd like to be able to use/port the search solution within Django so that my Django mirror site works the same way.

Anyone out there have an opinion?

0 Comments (Show) (Comments are closed for this post)

More

1 2 3 4 5 6 7 8
Please note that I am currently unavailable for any large, long term work.