play/type blog

We are creating Germany's juiciest event platform, boomloop.com. Because we love the Internet more than our own mothers. See for yourself. check out boomloop.com


It’s possible to write Linux desktop apps using ruby! All you need is a distribution running KDE 4.2. I have Kubuntu running on my Macbook.

First off, get the Ruby bindings installed:

apt-get install ruby-kde4

Next up, create a project directory for your Plasmoid. You can follow along with ‘Rakete’, which is my attempt at a Twitter client. The only thing Rakete does so far is to load and display an SVG.

you can call your root directory anything you like. In my case, it’s ‘application’ instread of ‘rakete’.

The `contents`directory holds the main files in a number of subdirectories. The most important of these is `code`, which, you guessed it, holds your ruby entry point, `main.rb`. `images` holds the SVG we want to render. You can create SVGs with a number of tools such as Adobe Illustrator or Inkscape (open source).

require 'plasma_applet'
module Rakete
class Main < PlasmaScripting::Applet
end
def initialize(parent, args = nil)
super
end
end
def init
@svg = Plasma::Svg.new(self)
@svg.imagePath = 'widgets/rakete'
end
def paintInterface(painter, option, contentsRect)
@svg.resize(size())
@svg.paint(painter, 0, 0)
end

`main.rb`should contain a class called `Main`, inside of a module named after your application. There are a number of callbacks you have to implement.

First off, you have ìnit`, which is called when the applet is first loaded. In here, we construct Plasma::Svg, which loads up rakete.svg.

SVGs are read from the svg.imagePath. This is relative to the $KDE_ROOT/apps/desktoptheme/default. KDE_ROOT varies from system to system. In the case of Kubuntu, it is /usr/share/kde4. So specifying an svg image path of

@svg.imagePath = 'widgets/rakete'

will mean that the svg is searched for under

/usr/share/kde4/apps/desktoptheme/default/widgets/rakete.svg

This lies outside of your Plasmoid directory structure, so the SVGs you package have to be staged into the widgets directory. Currently I don’t see any way of automating this staging process, so you’ll have to copy the svg from images/ over to the widgets directory. I’ll post more info as soon as I get it.

UPDATE 25.12.08: you can reference images inside of your plasmoid directory structure in your code. it turns out that doing so is very easy. applets have a `package` method, which returns an object representing your plasmoid package. the package object can resolve the canonical filename of your svg like this:

@svg.imagePath = package.file_path("images", "rakete.svg")

now you don’t need to worry about staging anything.

Next, create the metadata.desktop file:

[Desktop Entry]
Name=Rakete
Comment=an attempt at a better twitter plasmoid using ruby.
Icon=
Type=Service
ServiceTypes=Plasma/Applet
X-Plasma-API=ruby-script
X-KDE-PluginInfo-Author=Rany Keddo
X-KDE-PluginInfo-Email=purzelrakete@gmail.com
X-KDE-PluginInfo-Name=rakete
X-KDE-PluginInfo-Version=pre0.1
X-KDE-PluginInfo-Website=http://playtype.net
X-KDE-PluginInfo-Category=
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=MIT
X-KDE-PluginInfo-EnabledByDefault=true

Replace the pertinent field values.

Finally, you’ll want to run this thing. Run the following above the plasma root directory:

plasmapkg --upgrade application

This will install the Plasmoid on your system, or update it is already installed. Note that if you plasmoid root directory has a different name to “application”, you’ll need to cahnge the packaging command accordingly.

Finally, open the cashew in the top righthand corner of your desktop and select “Add Widget”. You’ll find your widget in the list.

As it stands, Plasma will sometimes crash when running this Applet. I’ll pass this information on to Richard Dale, the maintainer of the Ruby bindings. Hopefully he will be able to locate problems in the runtime, which is still in Beta1.

Richard was also super helpful in getting this example to run. Thank you Richard :-)

I’ll write more posts as I make progress with the Twitter client. You can find Rakete on Github.

Comments: 0 Show or write comments →  Tags: kde, plasma, ruby

Finally, I got around to installing Linux on my Macbook. I needed KDE 4.2 to try out the ruby bindings for Plasma. Here’s how to get Kubuntu up and running on top of VMWare Fusion on OSX with KDE 4.2.

First all, make sure you have the latest version of Fusion installed. If you don’t have Fusion, you can get a trial license here.

If you own a 1.0 Series version of Fusion, Fusion 2 is a free downloadable upgrade and will work with your existing serial number.

Next up, go and download Kubuntu 8.10 here. The download is not as big as you might think – I pulled it down within 10 minutes.

Once you’ve downloaded the image, start up Fusion and add a new Virtual Image with Apple-N. Click “Continue without Disk”, Now select “use operating system installation disk image file” and choose the Kubuntu Image file you just downloaded.

The Kubuntu installer will now launch. You will be asked if you want to boot off disk. Choose to install Kubuntu instead, then follow the rest of the installation process. Just pick the default options for everything.

Now you’ll have a running version of Kubuntu with KDE 4.1. You might find that the Fonts are too small when you launch programs such as the Terminal. If this is the case, go into the System Settings – Appearance – Fonts, and set “Force fonts DPI” to 96 DPI.

Next up, you can upgrade to KDE 4.2 if you like. As of writing, KDE 4.2 is still in Beta1 and only recommended for Developers. If you are following this along to try the Ruby bindings, or just want to see the most recent interface, then dive in :-)

To get on 4.2, follow these instructions from kde.org:

1.Remove the koffice-data-kde4 package. The current koffice2 packages are incompatible with the KDE 4.2 packages since they try to install icons to the same places.
2. Follow the Kubuntu Repository Guide to enable Recommended Updates and add the following to your ‘Third-Party Software’ tab:

deb http://ppa.launchpad.net/kubuntu-experimental/ubuntu intrepid main

3. You can now update any existing KDE 4 installation to the most recent version using the Adept Updater tool in your system tray.
4. Now log out and press Alt + E to restart X. When you log in you will have KDE 4.2 Beta 1.

Enjoy.

i’m currently looking for ruby web work. if you’re looking for an experienced developer or know of a project that is looking for developers, then please do contact me.

my preference is for remote work with onsite visits. send details to rany (at) playtype.net.

If you want to send mail asynchronously in your rails app, but don’t want to bother with using a queue server like Starling, then have a go at this…

First, run this:

./script/plugin install git://github.com/purzelrakete/workling.git
./script/plugin install git://github.com/langalex/workling_mailer.git
./script/plugin install git://github.com/matthewrudy/rudeq.git
rake queue:setup
rake db:migrate

now add this to your environment:

Workling::Clients::MemcacheQueueClient.memcache_client_class = RudeQ::Client
Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new

Finally, add this into the body of your mailer classes:

include AsynchMail

now start the workling client:

./script/workling_client start

done!

I did some refactoring this week, and the result is a much improved workling. Adding new work brokers is a snap now. I’ll show you how I added RabbitMQ, so that you can go about adding your own brokers. So without further ado…

RabbitMQ, a quick introduction

A lot of Ruby people have been talking about using RabbitMQ as their Queue of choice. Soundcloud.com are using it, as is new bamboo founder Johnathan Conway, who is using it at his video startup http://www.vzaar.com/. He says:

RabbitMQ – Now this is the matrons knockers when it comes to kick ass, ultra fast and scalable messaging. It simply rocks, with performance off the hook. It’s written in Erlang and supports the AMPQ protocol.

Follow the instructions here to get this beauty installed.

Adding Ampq to Workling

There are two new base classes you can extend to add new brokers. I’ll describe how this is done, but the code i show is already a part of workling. Skip to ‘activating amqp in your application’ to see how this is activated.

Clients

Clients help workling to connect to job brokers. To add an AmqpClient, we need to extend from Workling::Client::Base and implement a couple of methods.

require 'workling/clients/base'
require 'mq'

#
#  An Ampq client
#
module Workling
  module Clients
    class AmqpClient < Workling::Clients::Base

      # starts the client. 
      def connect
        @amq = MQ.new
      end

      # stops the client.
      def close
        @amq.close
      end

      # request work
      def request(queue, value)
        @amq.queue(queue).publish(value)
      end

      # retrieve work
      def retrieve(queue)
        @amq.queue(queue)
      end

      # subscribe to a queue
      def subscribe(queue)
        @amq.queue(queue).subscribe do |value|
          yield value
        end
      end

    end
  end
end

Were’s using the eventmachine amqp client for this, you can find it up on github. connect and close do exactly what it says on the tin: connecting to rabbitmq and closing the connection.

request and retrieve are responsible for placing work on rabbitmq. The methods are passed the correct queue, and a value that contains the worker method arguments. If you need control over the queue names, look at the RDoc for Workling::Routing::Base. In our case, there’s no special requirement here.

Finally, we implement a subscribe method. Use this if your broker supports callbacks, as is the case with amqp. This method expects to a block, which we pass into the amqp subscribe method here. The block will be called when a message is available on the queue, and the result is yielded into the block.

Having subscription callbacks is very nice, because this way, we don’t need to keep calling get on the queue to see if something new is waiting.

So now we’re done! That’s all you need to add RabbitMQ to workling. Configure it in your application as descibed below.

Invokers

There’s still potential to improve things though. Workling 0.4.0 introduces the idea of invokers. Invokers grab work off a job broker, using a client (see above). They subclass Workling::Remote::Invokers::Base. Read the RDoc for a description of the methods.

Workling comes with a couple of standard invokers, like the BasicPoller. This invoker simply keeps hitting the broker every n seconds, checking for new work and executing it immediately. The ThreadedInvoker does the same, but spawns a Thread for every Worker class the project defines.

So Amqp: it would be nice if we had an invoker that makes use of the subscription callbacks. Easily done, lets have a look:

require 'eventmachine'
require 'workling/remote/invokers/base'

#
#  Subscribes the workers to the correct queues. 
# 
module Workling
  module Remote
    module Invokers
      class EventmachineSubscriber < Workling::Remote::Invokers::Base

        def initialize(routing, client_class)
          super
        end

        #
        #  Starts EM loop and sets up subscription callbacks for workers. 
        #
        def listen
          EM.run do
            connect do
              routes.each do |queue|
                @client.subscribe(queue) do |args|
                  run(queue, args)
                end
              end
            end
          end
        end

        def stop
          EM.stop if EM.reactor_running?
        end
      end
    end
  end
end

Invokers have to implement two methods, listen and stop. Listen starts the main listener loop, which is responsible for starting work when it becomes available.

In our case, we need to start an EM loop around listen. This is because the Ruby AMQP library needs to run inside of an eventmachine reactor loop.

Next, inside of listen, we need to iterate through all defined routes. There is a route for each worker method you defined in your application. The routes double as queue names. For this, you can use the helper method routes. Now we attach a callback to each queue. We can use the helper method run, which executes the worker method associated with the queue, passing along any supplied arguments.

That’s it! We now have a more effective Invoker, which we can activate in our application like this…

Configuring your application to use AMQP (with RabbitMQ)

Again, follow the instructions here to get RabbitMQ running on your OSX development machine.

Workling::Remote.invoker = Workling::Remote::Invokers::EventmachineSubscriber
Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new
Workling::Remote.dispatcher.client = Workling::Clients::AmqpClient.new

enjoy!