Enhancing Streamlined Enumerations
Recently, I’ve been looking at the Streamlined framework. For those of you who don’t know, Streamlined is an Ajaxified Scaffold currently under development. The edge version shows promise and is stable enough for my personal use as an administration tool.
One area which is particularly interesting is the way that they handle enumerations and the fact that they are called late in the process rather than being instantiated once and then used. This may appear as an inefficiency at first glance, but in tracing through the call progress, I realized that you could make them more dynamic and allow for dynamic changes to the enumeration on a per item basis.
This means that if you have an exclusive list, you can restrict the choices to only those items that haven’t yet been assigned to other rows in the database.
For example, in one of my projects, you can assign a unique number to each row, and my desire was to restrict the view so that only the numbers that are available can be chosen.
So if you have possible numbers of
[1,2,3,4,5,6,7,8]
Assign 1 to the first row and for new items, [2,3,4,5,6,7,8] should be available, but [1,2,3,4,5,6,7,8] would be available for editing the first row.
Assign 5 to the second row and for new items, [2,3,4,6,7,8] should be available with [1,2,3,4,6,7,8] available for editing the first row and [2,3,4,5,6,7,8] available for editing the second row.
Coding this for the model is fairly straightforward:
class DynamicTest < ActiveRecord::Base
def available_nodes
node_list=[1,2,3,4,5,6,7,8]
nodes=DynamicTest.find(:all)
nodes.each do |n|
node_list-=[n.number] unless n.number==number
end
node_list
end
end
The unfortunate thing is that Streamlined doesn’t support this call, you can perform a call to DynamicTest.available_nodes, but that wouldn’t let you know what the current item is and you wouldn’t be able to see it in the list or edit views. Not very useful. What is needed is a way to call this directly from the row rendering code when you have the item in scope.
Since this is new functionality for Streamlined, the guys who maintain the codebase may adopt it, but for those of you who want to monkeypatch your own version or just see my take on it, you can download this sample project.
The monkeypatch (in app/streamlined/dynamic_tests_ui.rb) overrides four of the streamlined functions and adds two more for handling dynamic enumerations. This means that in addition to the original
Streamlined.ui_for(DynamicTest) do
user_columns :number, {:enumeration => Numbers::TYPES}
end
class Numbers
TYPES = [1,2,3,4,5,6,7,8]
end
and its Hash and 2d array counterparts, you can now have:
Streamlined.ui_for(DynamicTest) do
user_columns :number, {:enumeration => {:action=>:available_nodes}}
end
which will perform a late call to the DynamicTest#available_nodes scoped for the current row.
For those of you who just want to look at the code without downloading a full rails project, the relevant monkeypatched pieces are:
#Note: There is a bug in _enumeration.html that prevents non-Fixednum numeric
#indices. This should be updated in the template version
#<% value = item.send(relationship.name) -%>
#<% key_value_pair = relationship.enumeration_key_for(value) -%>
#<%= key_value_pair ? key_value_pair.first : relationship.unassigned_value %>
module Streamlined::Controller::EnumerationMethods
def dynamic_enumeration
dynamic_enumeration_method=nil
@enumeration_name=params[:enumeration]
rel_type=model_ui.scalars[@enumeration_name.to_sym]
rel_type.enumeration.each { |k,v|
dynamic_enumeration_method=v if k==:action
}
dynamic_enumeration_method.nil? ? rel_type.enumeration : instance.send(dynamic_enumeration_method).to_2d_array
end
# Shows the enumeration’s configured +Edit+ view, as defined in streamlined_ui
# and Streamlined::Column.
def edit_enumeration
self.instance = model.find(params[:id])
@enumeration_name = params[:enumeration]
rel_type = model_ui.scalars[@enumeration_name.to_sym]
@all_items=dynamic_enumeration
@selected_item = instance.send(@enumeration_name)
render(:partial => rel_type.edit_view.partial, :locals => {:item => instance, :relationship => rel_type})
end
# Show’s the enumeration’s configured +Show+ view,
# as defined in streamlined_ui and Streamlined::Column.
def show_enumeration
self.instance = model.find(params[:id])
rel_type = model_ui.scalars[params[:enumeration].to_sym]
rel_type.enumeration=dynamic_enumeration
render(:partial => rel_type.show_view.partial, :locals => {:item => instance, :relationship => rel_type})
end
end
class Streamlined::Column::ActiveRecord < Streamlined::Column::Base
def dynamic_enumeration(item)
dynamic_enumeration_method=nil
@enumeration.each { |k,v|
dynamic_enumeration_method=v if k==:action
}
dynamic_enumeration_method.nil? ? @enumeration : item.send(dynamic_enumeration_method)
end
def render_td_show(view, item)
if enumeration
content = item.send(self.name)
@enumeration=dynamic_enumeration(item)
key_value_pair = enumeration_key_for(content) # call wraps enumeration to 2d array, so check unnecessary
content = key_value_pair.first if key_value_pair
content = content && !content.blank? ? content : self.unassigned_value
content = wrap_with_link(content, view, item)
else
render_content(view, item)
end
end
def render_enumeration_select(view, item)
id = relationship_div_id(name, item)
@enumeration=dynamic_enumeration(item)
choices = enumeration #enumeration call wraps to 2d array so extra call is redundant
choices.unshift(unassigned_option) if column_can_be_unassigned?(parent_model, name.to_sym)
args = [model_underscore, name, choices]
args << {} << html_options unless html_options.empty?
view.select(*args)
end
end
Microsoft Surface Parody
Hot on the heels of the Microsoft Surface announcement, and the statement by Tim Berners Lee that various devices and integrated software packages will be talking to each other seemlessly over the internet, and that everything (electronic) will be more tightly integrated in the future (Does anyone want to say Web 4.0 before they are shot down for confusing the internet with the web?), came this spoof voiceover of the advertising that Microsoft has produced to try to show that they are still innovating in hardware.
The Woodcock in Beacon Hill
A favorite haunt of the blogging community, and now the home for all the meetings, is the Woodcock in Beacon Hill. Since we have met there on a number of occasions, and befriended the staff and landlord, this has become almost a home away from home for most of us.

Since the landlord is geek friendly, and has a sofa that I occasionally live on two of us have collaborated and created him a website. Check out our favorite haunt.
Complete Floors
I have another website on my portfolio. You can check out their work (and mine) at http://completefloorsltd.co.uk
Tree Surgery
New website development. Not in Ruby this time, but they are happy with the results. Check it out at http://butlerandbrown.com.
Realplayer streaming BBC to mp3 files
The BBC listen again facility allows you to play back audio broadcasts up to seven days after they originally air. That’s fine, unless you listen to most of your radio in the car, or away from your computer.
OK. So you can listen live, as long as you are in the UK, but sometimes I would like to listen to the last 3 episodes of Perelandra, and possibly find out what’s going on in Lionel Nimrod’s Inexplicable World, while on a plane, or driving around Seattle.
This is where Mplayer, and the title of this blog entry come in.
The basic premise is to use mplayer to stream an entry to the harddrive in PCM format (wav), convert from wav to mp3 and drop in onto an mp3 file.
The following snippet from a larger script demonstrates the basic principle.
#Input: $1 url
# $2 name of file to record to (excluding extension)
#
mplayer -prefer-ipv4 -bandwidth 99999999 -vc null -vo null -ao pcm:fast -ao pcm:file=$2.wav $1
lame $2.wav $2.mp3
rm $2.wav
With a high bandwidth, it takes roughly a minute to download and encode a programme. Renaming or naming files are pretty tedious to do however, so I started to look at listing programmes, such as bleb and the BBC’s own backstage listings in order to automate the process. Continue reading…
Rails IDE - Komodo 4.1
I’m a great believer in free software, most of my systems are run using Apache, MySQL, Linux, and Ruby, as I’m sure quite a lot of you are running also. I’m also a great believer in the right tool for the right job, even if that isn’t a free tool. After using several of the free offerings, I downloaded the 4.0 beta of Komodo IDE to see if it was the right tool for developing RubyOnRails apps.
It was a little clunky. The editor and syntax highlighting were fine, and the approach to extending language support was also great. (I use Haml and Sass, rather than RHtml and CSS) The debugger took up to a minute to hit breakpoints, however, and although it was possible to use it , it was a little more difficult than I would have liked.
4.1 has changed all of that for me. Currently in beta, it is fast and shows the great strides that they have achieved. The Pro version is simply the best IDE I have used for Rails, bar none. I purchased mine and use Komodo now almost exclusively on all of my projects. Version 4.1 is available as a Trial from here.
Update: 4.1 has become the official release version, and is no longer in Beta. I feel an upgrade coming on.
Solid State Aircraft
Even if the science is still not quite there yet, the CGI is great. This is just cool. I want one. I’m not responsible for the cruddy commentary from a geek who thinks he is funny, but I love it when people come up with new ways for using great ideas.
Bloggers in Hindhead, Haslemere and Farnham

Recently, I joined a small group of like minded individuals (social drinkers), under the guise of a blogger get together. I thought that this would be a one-off visit, or perhaps an occassional quarterly or monthly, a few blokes go down the pub and talk about computers. I couldn’t have been more wrong. You can read about our weekly (yes, weekly) exploits at More That Just Us. If you are in the area on a Thursday night. drop one of us a line, and pop-along. We are an eclectic bunch who just seem to enjoy company despite our varied tastes in other things.