MacRuby, WebKit and JS


I was working on a piece of code using MacRuby, Webkit and JavaScript. Calling JS from MacRuby is really straight forward but calling Ruby from JS is a but tricky. There is actually a known bug in MacRuby which was giving me a hard time. The bug should be fixed in 0.8 if everything goes according to plan. In the mean time here is a quick run down:

The JS bridge only works when using WebKit so we need to create a tiny browser to test our code. What we are going to do is to make an object available via JS and also trigger some JS to test the bridge both ways. Here is the full code:

On the object we want to make available via JS (instance of Cat), we have to make the methods available by defining def self.isSelectorExcludedFromWebScript(sel); false end

To trigger JS from Ruby, we use #evaluateWebScript on windowScriptObject. In our example we are using JQuery since it’s already loaded in the DOM. We also go full loop by printing out the result of JS calling a method on our Ruby object.

Here is the thing, MacRuby doesn’t have the age method compiled/registered yet so JS can’t call it. To fix this problem we force the registration of the method by doing: @kitty.respondsToSelector(“age”). Note that if #age was taking arguments, we would have to use @kitty.respondsToSelector(“age:”) and then evaluate the JS like that: @js_engine.evaluateWebScript(‘animal.age_(12)’)

Hopefully by the time you need to do something like that, MacRuby 0.8 will be released and you won’t have to worry about that :)

For more information about calling Obj-C/Ruby from JavaScript, read this doc.


Similar Posts
  1. #1 by Botanicus - October 19th, 2010 at 05:36

    def initialize(name = nil, age=nil)
    @name = name || ‘kitty’
    @age = age || 42
    end

    Why to assign nil when you can just assign the default values directly:

    def initialize(name = ‘kitty’, age=42)
    @name = name
    @age = age
    end

    Am I missing something?

    • #2 by Matt Aimonetti - October 19th, 2010 at 06:56

      Ahah, no, just some left over from another piece of code + some inattention. Thx :)

  2. #3 by Matt Aimonetti - October 19th, 2010 at 06:59

    Interesting wrapper example by Alex MacCaw: http://gist.github.com/633934

  3. #4 by nicholas audo - October 19th, 2010 at 07:28

    I’m not near my mac to test this atm, but does operate headlessly?

  4. #5 by Mars - October 19th, 2010 at 08:17

    Nicholas,

    WebView will operate headlessly, but it does have to be run within a GUI login session (use auto-login on your headless server.)

  5. #6 by themgt - October 27th, 2010 at 06:11

    I’m not at all familiar with Cocoa programming, but how does one use the NSRunLoop to let WebKit load the page and then continue on with the (ruby) program execution?

  1. No trackbacks yet.

Comments are closed.