Run Ruby Script Automator Action

| | Comments (2) | TrackBacks (0)

In a recent blog post, Jonathan Wight unveiled a custom action for Automator which can run Python code. His code uses PyObjC to allow the action to take advantage of all the Cocoa goodness that comes with it. While I am doing more Python work these days, my heart still belongs to Ruby, so I was compelled to respond with a “Run Ruby Script” action of my own.

RunRubyScript.png

The source code for this project is available under the MIT license. Like Jonathan’s Python original, this action includes a (rather naïve) syntax highlighting NSTextView. More on that perhaps in a future post. But the real star of this action is the integration with Leopard’s Scripting Bridge.

When Automator passes objects in to a custom Cocoa-based action, it converts them into one of a handful of possible Cocoa types. Types such as strings (com.apple.cocoa.string), paths (com.apple.cocoa.path), and URLs (com.apple.cocoa.url) are happily handled for you. Everything else can be sent as an Apple Event descriptor (com.apple.applescript.object). That’s all well and good, but I haven’t the foggiest what to do when my script receives an NSAppleEventDescriptor. What we really want is an object with methods and properties that can be used to access the underlying object directly. With the help of Scripting Bridge, this is no problem at all.

The Scripting Bridge essentially wraps the scriptable interface of an application up into a nice Objective-C object. With the help of RubyCocoa, we can take advantage of those nicely wrapped interfaces in the “Run Ruby Script” action. Since incoming data is passed in the form of an NSAppleEventDescriptor, the action performs some conversion in order to get a Scripting Bridge object for use by the script. By recursively traversing the descriptor, we can glean the source application and attempt to create an SBApplication. If that goes well, we work our way back up through the event descriptor, finding items in collections on our way back up. This is best illustrated by an example:

Imagine that we ask iTunes to find all songs whose name equals “The Salmon Dance” (a great song recently recommended by Cabel). We might normally get an NSAppleEventDescriptor such as

<NSAppleEventDescriptor: 'obj '{ 
    'form':'ID  ', 'want':'cFlT', 'seld':3592, 'from':
        'obj '{ 'form':'ID  ', 'want':'cLiP', 'seld':3322, 'from':
            'obj '{ 'form':'ID  ', 'want':'cSrc', 'seld':42, 'from':
                'psn '("iTunes") } } }
>

I don’t know about you, but my brain lost interest at 'want':'cFlT'. But let’s not give up yet. After invoking the powers of Scripting Bridge, we get

<ITunesFileTrack @0x12a5c40: 
    ITunesFileTrack id 3592 
    of ITunesLibraryPlaylist id 3322 
    of ITunesSource id 42 
    of application "iTunes" (98938)>

That gives me a warm fuzzy.

Download the action now! If you find it useful or come up with an interesting use for it in a workflow, drop me a line or leave a comment here. I’ll be updating the repository periodically with improvements and examples.

Words of warning: There may be some issues if you have both the Ruby and Python script actions installed. Specifically, Automator may crash if you try to add both actions into the same workflow. I described the problem in brief in my article about RubyCocoa bundles, and Bill Bumgarner described it in a bit more detail on his blog. The bug which causes this will hopefully be fixed in 10.5.2, but I may release a custom built version of RubyCocoa in the meantime if there is enough demand for it.

Categories

, , ,

0 TrackBacks

Listed below are links to blogs that reference this entry: Run Ruby Script Automator Action.

TrackBack URL for this entry: http://threeve.org/blog/mt/mt-tb.cgi/1

2 Comments

has said:

I think I've found a problem with your action. if the Run Ruby action returns Scripting Bridge references, and the next action is a Run AppleScript, the AppleScript action doesn't recognise the input/run correctly. (Drop us an email if you want a workflow file that demonstrates this.)

I'm not familiar with the deeper workings of Automator, but if I had to guess I'd suspect that your action returns SBObject instances whereas Automator needs NSAppleEventDescriptor instances for portability. As far as I can tell, the Scripting Bridge API doesn't provide any way to extract descriptors from SBObjects, so if that's the case then that's going to restrict the usefulness of your action somewhat unless you can find some way to hack it. Alternatively, I'm working on an Automator-compatible version of appscript for Jon's Python action; if you'd like to explore a Ruby version of the same then I'll be happy to discuss.

HTH

has
--
http://appscript.sourceforge.net
http://rb-appscript.rubyforge.org

Jess Stimpson Epps Jr. said:

App downloads with a "Canvas" icon.

Leave a comment

About this Entry

This page contains a single entry by Jason Foreman published on January 12, 2008 10:21 PM.

Loadable bundles using RubyCocoa was the previous entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by Movable Type 4.01