Enhancing Streamlined Enumerations

Posted by blackrat on March 26, 2008

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

Posted by blackrat on March 17, 2008

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

Posted by blackrat on November 10, 2007

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.
The Woodcock by Night
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

Posted by blackrat on August 20, 2007

I have another website on my portfolio. You can check out their work (and mine) at http://completefloorsltd.co.uk

Tree Surgery

Posted by blackrat on August 20, 2007

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

Posted by blackrat on August 02, 2007

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…

It’s 1973, almost dinnertime. I’m having ‘oops

Posted by blackrat on July 04, 2007


Rails IDE - Komodo 4.1

Posted by blackrat on May 23, 2007

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

Posted by blackrat on May 23, 2007

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

Posted by blackrat on May 03, 2007

Bloggers at the Farnham Beer Festival

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.