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

DRYing Up My Controllers

Posted on 07:00AM on 12/31/2008
Tags: ruby, rails

I'm working on a Rails project right now. It's been a while, since I've been doing most Ruby work with Sinatra lately.

Millions of posts have talked about DRYing up controllers. I'm not talking about the skinny controller/fat model concept, necessarily, although that should be addressed as well. What I'm refering to is the constant repetition in all controllers. A create action, for example, always has essentially the same code.

I'm not writing this post to claim that I've solved the problem in some unique, world changing way. I'm really just writing to acknowledge that I see it and have decided to deal with it. Repetition bugs me. Repeatedly spec'ing the same controller code bugs me.

The bottom line: I'm writing a module that can be included in my controllers that will remove the need to constantly add index, show, new, create, edit, update, destroy and the code that goes along with them. I will test it well. I will override in the controllers to handle special circumstances. My simple controllers should NOT need to be more that 50 lines long (if that).

I guess this is actually a New Year's resolution. So there!

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

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)

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)

Django Version Up And Running!

Posted on 09:11PM on 09/09/2008
Tags: sinatra, django, ruby, python

I was interested in comparing the speed of Sinatra/Ruby against Python/Django. Not in any scientific way, just as side-by-side apps.

As a result, I've created a Django version of this site.

So far, they both feel about equally responsive.

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

More

1 2
Please note that I am currently unavailable for any large, long term work.