Syspec: System Specifications & Tests using a Rake-like batch file

Posted over 7 years back at Wood for the Trees

Syspec lets you write a batch file a lot like a Rake file, but in common HTTP-style language, to test the existence and proper functioning of all the domains, subdomains, their pages and responses. This project is still very much in its infancy, but I decided to get it out there to get some feedback while I use it to track production servers. This is a sample Syspecfile:

check :"www.rubyonrails.org" do
  accept 200
  get "/"
  accept 404
  get "/syspec"
  get "/lacrima"
end

The above will check that http://www.rubyonrails.org/ responds with 200 and http://www.rubyonrails.org/syspec and http://www.rubyonrails.org/lacrima respond with 404. You can have multiple checks with the same domain and it does not have to be a symbol, though I prefer it that way.

Currently, Syspec features the following:
  • accept(*codes) – response code should be among these codes
  • get, post, delete, put (uses fetch(:request_method, url))
Upcoming features:
  • login “username”, “password”
  • body matching
  • forms
You can grab a copy of it directly from my SVN repository here:
  svn co http://mabs29.googlecode.com/svn/trunk/gems/syspec .
Or download the gem from within the SVN repository (later will be moved to rubyforge):
  svn export http://mabs29.googlecode.com/svn/trunk/gems/syspec/versions/syspec-0.2.1.gem .

Enjoy!

Syspec: System Specifications & Tests using a Rake-like batch file

Posted over 7 years back at Wood for the Trees

Syspec lets you write a batch file a lot like a Rake file, but in common HTTP-style language, to test the existence and proper functioning of all the domains, subdomains, their pages and responses. This project is still very much in its infancy, but I decided to get it out there to get some feedback while I use it to track production servers. This is a sample Syspecfile:

check :"www.rubyonrails.org" do
  accept 200
  get "/"
  accept 404
  get "/syspec"
  get "/lacrima"
end

The above will check that http://www.rubyonrails.org/ responds with 200 and http://www.rubyonrails.org/syspec and http://www.rubyonrails.org/lacrima respond with 404. You can have multiple checks with the same domain and it does not have to be a symbol, though I prefer it that way.

Currently, Syspec features the following:
  • accept(*codes) – response code should be among these codes
  • get, post, delete, put (uses fetch(:request_method, url))
Upcoming features:
  • login “username”, “password”
  • body matching
  • forms
You can grab a copy of it directly from my SVN repository here:
  svn co http://mabs29.googlecode.com/svn/trunk/gems/syspec .
Or download the gem from within the SVN repository (later will be moved to rubyforge):
  svn export http://mabs29.googlecode.com/svn/trunk/gems/syspec/versions/syspec-0.2.1.gem .

Enjoy!

ActiveRecord Association Extensions

Posted over 7 years back at zerosum dirt(nap) - Home

So this is probably old hat to a lot of you, but for those that don’t know, ActiveRecord Association Extensions are a seriously useful widget to have in your Batman Fantasy Camp utility belt.

You’ve no doubt noticed that when you define an association between models, you get a bunch of nifty methods on the resultant collection like push, delete, count, uniq, and so on. But what if you want some bit of functionality defined on an association that isn’t already baked in?

Why we can extend our associations to define our own methods, of course. Let’s see how…

Okay, so we have a relationship defined between two models: articles and opinions. An article has_many opinions. An opinion has a score on it, which is an integer between 1 and 10 representing how a user felt about the article.

Using Association Extensions we can define our own method on the association itself, called total_score:

class Article < ActiveRecord::Base
  has_many :opinions do
    def total_score
      sum(:score)
    end
  end
end

Now you can access this information by writing something like:

article.opinions.total_score

Damn, that’s intuitive. Maybe we want to add another method on the association to retrieve the average opinion of users who voted on this article today:

has_many :opinions do
  def average_opinion_today
    find(:all, :conditions => ["created_at >= current_date()"]).average
  end
end

article.opinions.average_opinion_today

And it gets better. If we find ourselves using the same extensions in more than one place, in true DRY spirit we can build a module and reuse it. When we use the :extend option in an association, we get all the methods in that module mixed in.

module MiscellaneousExtensions
  def average_opinion_today
    find(:all, :condition => ["created_at >= current_date()"]).average
  end

  def total_score
    sum(:score)
  end
end

class Article < ActiveRecord::Base
  has_many :opinions, :extend => MiscellaneousExtensions
end

I put this module in a subdirectory of lib called extensions. You’ll have to add that path to the config.load_paths in environment.rb in order for it to be recognized.

Using these sorts of extensions on my own project earlier today really helped me clean up some troublesome model code. I was just so amped up about it that I had to share.

For more information, see the ActiveRecord::Associations API Reference. Oh and a big shout out to Brian Hogan for pointing me in the right direction.

Too much politics for programmers

Posted over 7 years back at Ryan Tomayko's Writings

One thing I hate about not being able to keep as close an eye on the Python community is the lack of Ian Bicking:

Actually “merging” the two is probably unlikely. It’s the kind of weird political maneuver that open source projects don’t really do, unless they are part of weird “foundations” and have “managers” and stuff like that — it’s too much politics for programmers, and reeks of strategy and plans. You aren’t supposed to announce plans for your software, you are supposed to implement your plans and then announce them. If a merge happens, it should be more like a realization than a strategy.

If you have some spare time or are sick of reading blogs or whatever, I suggest lurking on Python related mailing lists, even if you don’t care about Python. The above is from Ian’s blog but little nuggets of insight like this are very common on the mailing lists. There’s so many smart folks over there…

ANSI Strings (2nd Edition)

Posted over 7 years back at Wood for the Trees

I had a couple of instances where I was adding to the ANSI_CODES constant and creating all sorts of ugly errors. Then a script of mine whispered in my ear its desire for meta-aliases. That prompted a small rewrite of the library.

Ansi codes are now dynamically defined and more easily manipulated without overcomplicating things. Also, I added an RSpec test to the repository for my own piece of mind and to help with refactoring a few things. I don’t know, should I give it a version number? Nah. Just ‘Second Edition’. I don’t envisage any other serious revisions to it any more. What I changed:

  • dumped the array structure for ansi codes
  • added a few non-colour ANSI codes
  • dynamic ansi code definitions: String.define_ansi :alias => “123m”
  • meta-aliases: String.define_ansi :clear_both => [:clear_line, :clear_screen]
  • String#method definitions only if it doesn’t exist already
  • String#method definitions on the fly
  • spec test

And here’s the code:

$ANSI ||= false

class String

  class << self

    attr_accessor :ansi_codes

    def ansi_codes
      @ansi_codes ||= {}
    end

    def define_ansi(definitions = {})
      self.ansi_codes = ansi_codes.merge(definitions)
      define_shortcuts(definitions)
    end

    def define_shortcuts(definitions = {})
      definitions.keys.each do |meth|
        unless instance_methods.include?(meth.to_s)
          define_method(meth) { with_ansi(meth) }
        end
      end
    end

  end

  define_ansi :normal         => "0m",      :bold           => "1m"
  define_ansi :underline      => "4m",      :blink          => "5m"
  define_ansi :reverse_video  => "7m",      :invisible      => "8m"
  define_ansi :black          => "30m",     :red            => "31m"
  define_ansi :green          => "32m",     :yellow         => "33m"
  define_ansi :blue           => "34m",     :magenta        => "35m"
  define_ansi :cyan           => "36m",     :white          => "37m"
  define_ansi :black_bg       => "40m",     :red_bg         => "41m"
  define_ansi :green_bg       => "42m",     :yellow_bg      => "43m"
  define_ansi :blue_bg        => "44m",     :magenta_bg     => "45m"
  define_ansi :cyan_bg        => "46m",     :white_bg       => "47m"
  define_ansi :clear_line     => "K",       :clear_screen   => "2J"
  define_ansi :go_home        => "0H",      :go_to_end      => "80L"

  # Wrap a string with an arbitrary ansi code and the ansi normal code
  def with_ansi(*codes)
    use_ansi? ? "#{sym_to_ansi(*codes)}#{self}#{sym_to_ansi(:normal)}" : self
  end

  # Just a little metaprogramming shortcut
  def ansi_codes; self.class.ansi_codes; end

  private
  def sym_to_ansi(*symbols)
    symbols.inject("") do |string, symbol|
      if code = ansi_codes[symbol]
        string << (code.is_a?(Array) ? sym_to_ansi(*code) : "\e[#{code}")
      end
      string
    end
  end

  # determine whether we have ansi support or ANSI enabled
  def use_ansi?
    $ANSI && RUBY_PLATFORM !~ /win32/i
  end

end

You can grab the new version from my ‘other’ directory at Google Code:

  svn co http://mabs29.googlecode.com/svn/trunk/other/ansi_strings .

ANSI Strings (2nd Edition)

Posted over 7 years back at Wood for the Trees

I had a couple of instances where I was adding to the ANSI_CODES constant and creating all sorts of ugly errors. Then a script of mine whispered in my ear its desire for meta-aliases. That prompted a small rewrite of the library.

Ansi codes are now dynamically defined and more easily manipulated without overcomplicating things. Also, I added an RSpec test to the repository for my own piece of mind and to help with refactoring a few things. I don’t know, should I give it a version number? Nah. Just ‘Second Edition’. I don’t envisage any other serious revisions to it any more. What I changed:

  • dumped the array structure for ansi codes
  • added a few non-colour ANSI codes
  • dynamic ansi code definitions: String.define_ansi :alias => “123m”
  • meta-aliases: String.define_ansi :clear_both => [:clear_line, :clear_screen]
  • String#method definitions only if it doesn’t exist already
  • String#method definitions on the fly
  • spec test

And here’s the code:

$ANSI ||= false

class String

  class << self

    attr_accessor :ansi_codes

    def ansi_codes
      @ansi_codes ||= {}
    end

    def define_ansi(definitions = {})
      self.ansi_codes = ansi_codes.merge(definitions)
      define_shortcuts(definitions)
    end

    def define_shortcuts(definitions = {})
      definitions.keys.each do |meth|
        unless instance_methods.include?(meth.to_s)
          define_method(meth) { with_ansi(meth) }
        end
      end
    end

  end

  define_ansi :normal         => "0m",      :bold           => "1m"
  define_ansi :underline      => "4m",      :blink          => "5m"
  define_ansi :reverse_video  => "7m",      :invisible      => "8m"
  define_ansi :black          => "30m",     :red            => "31m"
  define_ansi :green          => "32m",     :yellow         => "33m"
  define_ansi :blue           => "34m",     :magenta        => "35m"
  define_ansi :cyan           => "36m",     :white          => "37m"
  define_ansi :black_bg       => "40m",     :red_bg         => "41m"
  define_ansi :green_bg       => "42m",     :yellow_bg      => "43m"
  define_ansi :blue_bg        => "44m",     :magenta_bg     => "45m"
  define_ansi :cyan_bg        => "46m",     :white_bg       => "47m"
  define_ansi :clear_line     => "K",       :clear_screen   => "2J"
  define_ansi :go_home        => "0H",      :go_to_end      => "80L"

  # Wrap a string with an arbitrary ansi code and the ansi normal code
  def with_ansi(*codes)
    use_ansi? ? "#{sym_to_ansi(*codes)}#{self}#{sym_to_ansi(:normal)}" : self
  end

  # Just a little metaprogramming shortcut
  def ansi_codes; self.class.ansi_codes; end

  private
  def sym_to_ansi(*symbols)
    symbols.inject("") do |string, symbol|
      if code = ansi_codes[symbol]
        string << (code.is_a?(Array) ? sym_to_ansi(*code) : "\e[#{code}")
      end
      string
    end
  end

  # determine whether we have ansi support or ANSI enabled
  def use_ansi?
    $ANSI && RUBY_PLATFORM !~ /win32/i
  end

end

You can grab the new version from my ‘other’ directory at Google Code:

  svn co http://mabs29.googlecode.com/svn/trunk/other/ansi_strings .

Simple Captcha Released

Posted over 7 years back at Ajax on Rails


Hey guys, finally i have released the captcha plugin for public usage.

Check it out here

WS-* == Windows Services Dash Star?

Posted over 7 years back at Ryan Tomayko's Writings

Tim said it:

WS-*? In the real world, it’s about being able to interoperate with WCF, and while that’s a worthwhile thing, that’s all it’s about. It’s not like HTTP or TCP/IP, truly interoperable frameworks, it’s like DCOM; the piece of Windows’ network-facing surface that Microsoft would like you to code to. For now, anyhow; it’ll be at least as easy as DCOM to walk away from when the embarrassment gets too great.

Holy crap.

Has it really slid this far out of control already? I was thinking the industry could keep to their talking points and rip off a few thousand more clueless IT managers over the next few years but when Gartner gives up on you, it’s a pretty safe bet that your days are numbered.

Engines 1.2 Released

Posted over 7 years back at Rails Engines News

I’ve just pushed the 1.2 release of the engines plugin forward as the official release found by script/plugin. The 1.2 release is compatible with Rails 1.2, and undoubtedly the best release so far. It’s never been easier to make your plugins more powerful, and I’m very happy with some of the new features 1.2 gives, including routes in plugins and a new “best-practise” for sharing migrations.

Engines are dead…

The new 1.2 release also represents a psychological “reboot” for the engines plugin. Thanks to some of the features we managed to contribute to Rails itself, any plugin can be enhanced by the engines plugin. This is the final blow to the unfortunate misunderstanding that “engines are evil”, because there’s literally no such thing as “an engine” anymore. The engines plugin is just a plugin that makes other plugins more powerful.

Below the cut you can read about some of the enhancements that the engines plugin contributes to making sharing code amongst your projects even simpler.

Continue Reading…

The Camping Episode - Ruby on Rails Podcast

Posted over 7 years back at Ruby on Rails Podcast

Three interviews with developers who use why the lucky stiff’s Camping framework.
See also

Refactoring REST: searching for an abstraction

Posted over 7 years back at Luke Redpath - Home

It’s been a while since I blogged. Sorry about that. Needless to say, it’s been a hectic couple of months. Birthdays, Christmas, New Year, a new job; all found their way towards keeping me from that big shiny text-box in Mephisto’s admin interface. For those still waiting for part two of my RSpec tutorial – and I know I’ve said this several times already – it will be coming; I’m just not sure when yet. There are some interesting developments afoot in the world of RSpec and I’ll be waiting until these make it into the next major release before tackling the article.

In this article, I’d like to talk about REST. The world of REST and resources has been a part of the Rails edge for a while now, since the last RailsConf in fact and whilst skeptical at first, I’ve really come around to the concept of RESTful resources. Whilst I still feel that it is not always suitable I’ve found that the best approach is combination of RESTful controllers and RPC-style controllers where necessary. One of the great things about the RESTful approach is that it really brings the idea of good object-oriented design – specifically the idea of objects having a clear focus on a particular task – to Rails controllers. The downside is that normalization of REST-style controllers has led to, in my experience, a lot of repetitive code. And as every good programmer knows, duplication should be hunted down and destroyed whenever possible.

The wonderful world of REST

The RESTful resources concept focusses on seven core actions: index, show, new, create, edit, update and destroy. These actions expose four core behaviours of your ActiveRecord objects through some of the various verbs available in the HTTP spec: retrieval (GET), creation (POST), updating (PUT) and deletion (DELETE). If you’ve been working with RESTful resources for any length of time you will find that the code for each of these actions tends to look very similar largely due to the use of convention over configuration that Rails favours heavily.

Whilst looking at refactoring portions of our company intranet, it struck me that such duplication was rife and I set about eliminating it. Ever mindful that the best abstractions are extracted (just like Rails was), all of the ideas and code that follows have been extracted directly from our intranet application.

I’m not the only person who has recognised the duplication that tends to result from taking the RESTful approach and consequently some solutions for making development of RESTful applications exist already in the form of generators and scaffolding.

Existing solutions

The problem with generators is that they don’t actually solve the problem of duplication in the code – they simply make it easier to get up and running by generating boilerplate code for you to modify. But once the code is in place it is still something to be maintained.

The problem with scaffolding is the same problem that plagues the scaffolding that originally came with Rails – it provides a very generic abstraction with little in the way of flex points which means you usually end up overriding the scaffolded methods anyway. You can usually generate scaffolding directly into the source itself but this has all of the same problems as generators.

An alternative approach

My approach was to first attempt some small, fine-grained refactorings on my controllers such as Extract Method to make sure that the REST actions focussed on their core responsibilities and delegated to template methods for specific behaviour. A common example is the create action, which usually looks something like this:

def create
  @user = User.new(params[:user])
  if @user.save
    flash[:notice] = 'User created successfully'
    redirect_to user_url(@user)
  else
    flash[:error] = 'User creation failed'
    # some specific error handling
    render :action => 'new'
  end
rescue SomeException
  # exception handling here
end

After extracting functionality to template methods, I ended up with code like this:

def create
  user = User.new(params[:user])
  if user.save
    handle_successful_create_for user
  else
    handle_failed_create_for user
  end
rescue
  handle_exception_for_user
end

protected
  def handle_succesful_create_for user
    flash[:notice] = 'User creeated successfully'
    redirect_to user_url(user)
  end
    
  def handle_failed_create_for user
    @user = user
    flash[:error] = 'User creation failed'
    render :action => 'new'
  end

  def handle_exception_for user
    # exception handling here
  end

The same approach is taken for other methods and after making this refactoring I am now left with identical RESTful actions across my application. Some might feel that the next step was to extract a super-class but there was still some variation that hadn’t been eliminated – each controller worked with a different model. I was also somewhat uneasy about using inheritance to eliminate duplication – it is often a good idea to favour composition where possible1. However a solution that uses composition is awkward because the object model for Rails controllers is abstracted in the framework. Fortunately Ruby provides us with an alternative that allows us to avoid modifying the inheritance tree in the form of mixins. Using include and extend we are able to add functionality to classes and their instances. This is the approach I decided to take but that still left that pesky model variation to deal with.

Refactoring further: extending the DSL

Once again Ruby comes to the rescue with it’s excellent meta-programming functionality. We take advantage of that functionality all of the time in Rails when we use it’s macro-style class methods; filters and ActiveRecord associations and validations are great examples. Using meta-programming, it was relatively easy to come up with a small DSL for exposing resources with a controller. Here is the first part:

class UsersController < ApplicationController
  expose_resource :user
end

As it clearly states, this tells the UsersController that we want to expose our User model. We can use this value throughout whatever code we write to generate each action. The next thing to tackle was how to generate these actions at runtime. I studied the scaffolding code that comes with Rails but wasn’t really comfortable with treating code as a template and running it through an eval statement. I decided to take a more object-oriented approach and created a series of command objects to represent each action. This solution was easy to test and extend where necessary.

Finally, there needed to be some way of specifying what actions RESTful actions you want to expose – you might not want all seven. This lead to the second part of the DSL:

class UsersController < ApplicationController
  expose_resource :user, :except => [:update, :destroy]
end

Of course, you might only want a few of the actions:

class UsersController < ApplicationController
  expose_resource :user, :only => [:index, :show]
end

So where does that leave us? All of the core functionality is in place and all that the developer has to provide is an implementation of the various callback handlers. With some sensible default implementations to these handlers built-in, the developers life is made even easier.

One size does not fit all

It is worth noting that there isn’t a callback handler designed for every situation. Besides the sheer difficulty in guessing all of the flex-points that a developer might need, it would require a lot of bloated unnecessary code just to cater for edge cases. The above abstraction was never designed to cover all cases and I don’t believe any abstraction ever can. However it does make it possible to add functionality quickly at least 80% of the time and it handling the remaining 20% of cases is as simple as the developer providing their own hardcoded action.

All of the code discussed above is available as a Rails plugin that I’ve called restful_exposure. It can be checked out with Subversion at the following URL:

svn://lukeredpath.co.uk/opensource/plugins/restful_exposure/trunk

A README is bundled and all code is released under the MIT license.

Feedback

At present, most of the callback handlers are lacking implementation. This code is only a couple of days old and is not considered production-ready by a long shot. For starters, it is completely lacking any form of test coverage. I used our existing test coverage for our intranet to guide my way during refactoring but it is my plan to add a good suite of RSpec specifications. This isn’t even live on our intranet yet and currently lives on a branch of our intranet code.

In addition to the above functionality there are a few other features that came about as a direct result of extracting this from our intranet application. The first is the introduction of a parameterized index action. It is common to have some alternative collection actions as well as index – archives, search and recent are good examples. They both retrieve a collection of objects but the number of items retrieved, their order and how they are filtered varies. This variation is encapsulated by the index parameter which is passed into ActiveRecord::Base#find as its options hash. This lets you do things like this:

def recent
  index :limit => 5
end

Another thing that it was important to handle was nested resources, representing belongs_to/has_x relationships. One of the impacts this had on the code was in the creation of new objects – the new action had to ensure that the new object created (to be bound to the new form) was linked to its parent object. Getting the parameters for this is made easy by convention and URL parameters made available by nested resource routes so it wasn’t a problem to extract. This lead to the first option for expose_resource:

class FilesController < ApplicationController
  expose_resource :file, :nested_under => :folder
end

The second option came from the need to link new objects to their parent object when working with tree-like nesting of a single model using acts_as_tree. Support for this is built-in using the as_tree option:

class FolderController < ApplicationController
  expose_resource :folder, :as_tree => true
end

I’m well aware that the Rails community is an opionated one (naturally) and that this might not appeal to some people. Some people might perceive this as “too much magic”. Personally I’d disagree – I think this is no more magic here than has_many and acts_as_foo. It has been extracted from a real working application and I think that is important. I have a “3 strikes” rule when it comes to abstractions like this – if I’ve done the same thing three different times or on three different apps then its time to look for that abstraction and reduce the amount of code that needs maintaining. This “3 strikes”/abstract through extraction approach is exactly the same one that lead to my crypted_authentication plugin.

If you are working with RESTful resources and have found yourself typing the same thing over and over again, please do checkout the plugin and give it a try. I repeat, this is not production-ready but I’m really interested in people’s feedback on the approach and any suggestions. Do dig into the source to get an understanding of how I’ve approached the implementation. I’ve tried to avoid Ruby-fu “magic” wherever I can in favour of traditional object-oriented approaches.

Are there any areas such as the nesting/tree-like structures above that you find yourself doing often that would be a good fit for abstraction? What do you think of the API? Comments are open!

Update 05/02/2007: As per Steve’s suggestion in the comments below, I’ve modified the interface so that it uses just the single expose_resource call, with :only and :except options (:all by default) as per the Rails filters API. I’ve updated the code samples above to reflect this. expose_resource_actions has been removed.

1 It is a generally accepted object-oriented design rule – and one that I agree with and try to adhere to – that composition leads to less coupling and polution of the inheritance tree (which should really only really be used when objects really are of similar type). I also find it leads to more easily testable and elegant solutions.On Google.

Blog moved to Expressica.com — releasing the captcha plugin with multiple styles of clear images, with random string text

Posted over 7 years back at Ajax on Rails


Hi Everbody !!

I am moving this blog to Expressica

and i would like to inform all the readers to update their feeds and bookmarks to the new url http://expressica.com .

On my new blog i am going to release a captcha plugin which is really very simple to implement. This plugin provides the functionality to add captcha based authentication in your rails applications.

It mainly features…

  • Controller based captcha
  • Model based captcha
  • and the feature i like the most is multiple image styles

You can simply pass the name of the image style from the view and captcha will throw the random strings as the selected style of image. The images are clear enough to read by human and blurred and manipulated enough to protect from bots.
Example of the images …

  • simply_red
  • simply_green
  • simply_blue
  • embosed_silver
  • distorted_black
  • all_black
  • charcoal_grey
  • almost_invisible

Comments/Queries are welcome on this idea.

I will release this plugin very soon on Expressica.com

ANSI Strings: your fun-loving, colourful pal (quick-fix colour library)

Posted over 7 years back at Wood for the Trees

You can make your command line interface look a little better than just a bungle of white on black (or however you or your users set your terminal). In my on-going development of a few little open source projects, all of them with CLIs, I abstracted this cute addition to the Ruby snippets junkyard and decided to air it.

With it, you can wrap any string with ANSI codes like this:

  "I am going to be bold and cyan!".bold.cyan
  "I am going to be underlined. YAY!".underline
  "Oh, for the love of God... please STOP BLINKING!".blink

Make your command line interface glisten with choice and sparing use of ANSI codes not just with the above methods dynamically added to the String class, but also by using with_ansi(*ansi_aliases). It’s really very simple. Also, all application of ANSI is dependent on $ANSI being true, which, by default, is false (as you can at the bottom of this article, in the first line of code). Lastly, ANSI Strings checks the current platform and won’t be applied to strings on a win32 platform—I have no way of testing whether win32 can in certain instances show colour, so I just disable it.

You can download ANSI Strings from my googlecode repository like so:

 svn co http://mabs29.googlecode.com/svn/trunk/other/ansi_strings

Or you can just look at it here, since it is so simple and small:

$ANSI ||= true

class String

  ANSI_CODES = {
    :normal         => [0, "m"],
    :bold           => [1, "m"],
    :underline      => [4, "m"],
    :blink          => [5, "m"],
    :reverse_video  => [7, "m"],
    :invisible      => [8, "m"],

    :black          => [30, "m"],
    :red            => [31, "m"],
    :green          => [32, "m"],
    :yellow         => [33, "m"],
    :blue           => [34, "m"],
    :magenta        => [35, "m"],
    :cyan           => [36, "m"],
    :white          => [37, "m"],

    :black_bg       => [40, "m"],
    :red_bg         => [41, "m"],
    :green_bg       => [42, "m"],
    :yellow_bg      => [43, "m"],
    :blue_bg        => [44, "m"],
    :magenta_bg     => [45, "m"],
    :cyan_bg        => [46, "m"],
    :white_bg       => [47, "m"]
  }

  # Create shortcuts to wrap any string with ansi codes
  ANSI_CODES.keys.each { |meth| define_method(meth) { with_ansi(meth) } }

  # Wrap a string with an arbitrary ansi code and the ansi normal code
  def with_ansi(*codes)
    use_ansi? ? "#{sym_to_ansi(*codes)}#{self}#{sym_to_ansi(:normal)}" : self
  end

  private
  def sym_to_ansi(*symbols)
    symbols.inject("") do |string, symbol|
      string << "\033[%s%s" % ANSI_CODES[symbol] if ANSI_CODES[symbol]; string
    end
  end

  # determine whether we have ansi support or ANSI enabled
  def use_ansi?
    $ANSI && RUBY_PLATFORM !~ /win32/i
  end

end

ANSI Strings: your fun-loving, colourful pal (quick-fix colour library)

Posted over 7 years back at Wood for the Trees

You can make your command line interface look a little better than just a bungle of white on black (or however you or your users set your terminal). In my on-going development of a few little open source projects, all of them with CLIs, I abstracted this cute addition to the Ruby snippets junkyard and decided to air it.

With it, you can wrap any string with ANSI codes like this:

  "I am going to be bold and cyan!".bold.cyan
  "I am going to be underlined. YAY!".underline
  "Oh, for the love of God... please STOP BLINKING!".blink

Make your command line interface glisten with choice and sparing use of ANSI codes not just with the above methods dynamically added to the String class, but also by using with_ansi(*ansi_aliases). It’s really very simple. Also, all application of ANSI is dependent on $ANSI being true, which, by default, is false (as you can at the bottom of this article, in the first line of code). Lastly, ANSI Strings checks the current platform and won’t be applied to strings on a win32 platform—I have no way of testing whether win32 can in certain instances show colour, so I just disable it.

You can download ANSI Strings from my googlecode repository like so:

 svn co http://mabs29.googlecode.com/svn/trunk/other/ansi_strings

Or you can just look at it here, since it is so simple and small:

$ANSI ||= true

class String

  ANSI_CODES = {
    :normal         => [0, "m"],
    :bold           => [1, "m"],
    :underline      => [4, "m"],
    :blink          => [5, "m"],
    :reverse_video  => [7, "m"],
    :invisible      => [8, "m"],

    :black          => [30, "m"],
    :red            => [31, "m"],
    :green          => [32, "m"],
    :yellow         => [33, "m"],
    :blue           => [34, "m"],
    :magenta        => [35, "m"],
    :cyan           => [36, "m"],
    :white          => [37, "m"],

    :black_bg       => [40, "m"],
    :red_bg         => [41, "m"],
    :green_bg       => [42, "m"],
    :yellow_bg      => [43, "m"],
    :blue_bg        => [44, "m"],
    :magenta_bg     => [45, "m"],
    :cyan_bg        => [46, "m"],
    :white_bg       => [47, "m"]
  }

  # Create shortcuts to wrap any string with ansi codes
  ANSI_CODES.keys.each { |meth| define_method(meth) { with_ansi(meth) } }

  # Wrap a string with an arbitrary ansi code and the ansi normal code
  def with_ansi(*codes)
    use_ansi? ? "#{sym_to_ansi(*codes)}#{self}#{sym_to_ansi(:normal)}" : self
  end

  private
  def sym_to_ansi(*symbols)
    symbols.inject("") do |string, symbol|
      string << "\033[%s%s" % ANSI_CODES[symbol] if ANSI_CODES[symbol]; string
    end
  end

  # determine whether we have ansi support or ANSI enabled
  def use_ansi?
    $ANSI && RUBY_PLATFORM !~ /win32/i
  end

end

Blog Package Ponderings

Posted over 7 years back at zerosum dirt(nap) - Home

Drupal has served me pretty well for a number of projects in the past. But as we shift our development focus towards Ruby-based projects, it seems like an ideal time to consider migrating my own blogging platform to something Rails-driven. Nothing against Drupal itself of course. Hell, for a PHP project it’s pretty slick.

But it still just leaves me feeling like I’m flirting with an old (and somewhat unattractive) ex-girlfriend. It’s not you, it’s me.

The obvious candidates seem to be Typo and Mephisto. Another option would be to, of course, roll my own. But does the world really need another half-baked blogging engine? Probably not. If anyone has other recommendations let me know. Looks like I’m leaning towards Mephisto at this point.