Guide

Understanding Object Specifiers

RubyOSA bridges Ruby to a Mac OS X application. The objects that RubyOSA return are actually proxies that represent data on the application side. These objects act like normal Ruby objects but transparently communicate back to the Mac OS X application via Apple events.

Object Specifiers

You can think of objects returned by RubyOSA as pointing to the real application objects. These objects are called object specifiers. For example, the following object specifier points to the 41st track of your iTunes library:

OSA.app('iTunes').sources[0].playlists[0].tracks[42]

By default, RubyOSA doesn't resolve object specifiers for you. This means that no Apple event will be sent when interpreting the expression above.

RubyOSA will use the metadata from the scriptable definition to properly type object specifiers. Sometimes you may need to get the real type of the object. This can be done by resolving the object specifier, and this requires an Apple event. You can do this using the #get method:

track = OSA.app('iTunes').sources[0].playlists[0].tracks[42]

track.class()       # -> OSA::ITunes::Track
track.get.class()   # -> OSA::ITunes::FileTrack

You can also set the OSA.lazy_events global variable to false to automatically resolve all object specifiers (see the Changing the Global Settings section for more details).

Object Specifier Lists

You may have noticed that RubyOSA doesn't return real Array objects but OSA::ObjectSpecifierList objects.

OSA.app('iTunes').sources   # -> OSA::ObjectSpecifierList

This specific class mixes the Enumerable module so that you can call almost all Array methods on it. RubyOSA doesn't convert to real Array objects for performance reasons.

You can convert an OSA::ObjectSpecifierList object to a Ruby Array by calling the #get method on it. Note that this will automatically resolve all objects specifiers in the list as well:

OSA.app('iTunes').sources.get # -> [OSA::ITunes::Source, ...]

The classes of object specifiers can hold attributes. For example, the OSA::ITunes::Item class has a name property. RubyOSA provides a convenience facility to collect all of the attributes of a given name from an object specifier list:

OSA.app('iTunes').sources.every(:name) # -> ["Library", "Radio"]

The main advantage of using #every is that only one Apple event will be sent. The following code returns the same value but requires two Apple events to be sent:

OSA.app('iTunes').sources.map { |s| s.name }

Using #every can make a difference when working on a large collection of objects.