Archive for the ‘Rubyonrails’ Category

Ruby Bindings for Qt: Building QtRuby on MeeGo and creating an RPM

Tuesday, August 10th, 2010

MeeGo is great. What could make it even better? More Ruby :-) So what better way to achieve this than by getting the Ruby bindings for Qt up and running on MeeGo. So here’s a Work In Progress guide…

Pre-requisites
Get the MeeGo SDK running on your machine under Xephyr http://wiki.meego.com/MeeGo_SDK_with_Xephyr
I’ll assume that you can successfully run the meego-sdk-chroot command and are now at a MeeGo console. Here’s what we need to do to build QtRuby…

The Guide
Install cmake:
zypper in cmake

Pull down the kdebindings source code from svn:
svn checkout -N svn://anonsvn.kde.org/home/kde/trunk
cd trunk
svn up -N KDE
cd KDE
svn up kdelibs kdebindings
# The above should be all you need to do but if you have problems then maybe try reading http://en.opensuse.org/openSUSE:KDE_developers_guide

Copy the kdebindings/qtruby directory to your meego home directory in the <meego_sdk_directory>, the latter will be something like /home/yourusername/meego-sdk-0524/home/meego/ depending on where you installed the MeeGo SDK earlier.

Copy the file kdebindings/CMakeLists.txt.qtruby to /home/meego/qtruby/CMakeLists.txt (yes, this will overwrite the old file. This is ok, we don’t want to build all of kdebindings, just qtruby)

cd <meego_sdk_directory>/home/meego/qtruby

Edit the new CMakeLists.txt, underneath the line “include (MacroOptionalFindPackage)” add the lines:
include (MacroOptionalAddBindings)
include (MacroLogFeature)
include (CheckCXXSourceCompiles)

Also, just before the line “add_subdirectory(smoke)” add the ine:
add_subdirectory(generator)

Finally, if you want to be able to build an RPM (or any other package type supported by the CPack tool), add the following line as the very last line in the CMakeLists.txt file:
include(CPack)

Ok now we need to create a cmake/modules directory
mkdir -p qtruby/cmake/modules

cd qtruby

As the CMakeLists.txt file says in the commented section, we need to copy some files we need from the KDE related directories (this is because we are building QtRuby standalone instead of as part of the all-encompasing kdebindings module). Note, you need to change the location of kdelibs in the next command to wherever you pulled down the subversion directory

cp kdelibs/cmake/modules/FindQt4.cmake ./cmake/modules/
cp kdelibs/cmake/modules/FindRUBY.cmake ./cmake/modules/
cp kdelibs/cmake/modules/MacroOptionalFindPackage.cmake ./cmake/modules/
cp kdelibs/cmake/modules/MacroPushRequiredVars.cmake ./cmake/modules/

Additionally you will need to copy the following files

cp kdelibs/cmake/modules/Qt4Macros.cmake ./cmake/modules/
cp kdelibs/cmake/modules/Qt4ConfigDependentSettings.cmake ./cmake/modules/
cp kdelibs/cmake/modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake ./cmake/modules/
cp kdelibs/cmake/modules/MacroLogFeature.cmake ./cmake/modules/
cp kdelibs/cmake/modules/CheckCXXSourceCompiles.cmake ./cmake/modules/

And also copy these from kdebindings

cp kdebindings/cmake/modules/MacroOptionalAddBindings.cmake ./cmake/modules/
cp -r kdebindings/ruby .
cp -r kdebindings/smoke .
cp -r kdebindings/generator .

Now we are going to create a qtruby_build directory so that we can do an out-of-source build of qtruby. If you don’t know what an out-of-source build is, don’t worry!
cd ..
mkdir qtruby_build
cd qtruby_build

Create a file called cmake_qtruby. Copy and paste the long commented cmake command in CMakeLists.txt to this file (you can exclude the make and make install commands)

At the end of the last line of this command add a backslash (so that you can continue the command on the next line) and then add the line:
../qtruby

Then change the cmake command options
-DRUBY_EXECUTABLE=/usr/bin/ruby
-DRUBY_INCLUDE_PATH=/usr/lib/ruby/1.8/i386-linux/

At the end of this step the file should look something like

cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DRUBY_EXECUTABLE=/usr/bin/ruby \
-DRUBY_INCLUDE_PATH=/usr/lib/ruby/1.8/i386-linux/ \
-Wno-dev \
-DENABLE_SMOKE=on \
-DENABLE_QTRUBY=on \
-DENABLE_QTWEBKIT_SMOKE=off \
-DENABLE_QTSCRIPT_SMOKE=off \
-DENABLE_QTUITOOLS_SMOKE=off \
-DENABLE_QTTEST_SMOKE=off \
-DENABLE_PHONON_SMOKE=off \
-DENABLE_QSCI_SMOKE=off \
-DENABLE_QWT_SMOKE=off \
-DENABLE_KDE_SMOKE=off \
-DENABLE_KDEVPLATFORM_SMOKE=off \
-DENABLE_KHTML_SMOKE=off \
-DENABLE_KTEXTEDITOR_SMOKE=off \
-DENABLE_SOLID_SMOKE=off \
-DENABLE_PLASMA_SMOKE=off \
-DENABLE_QTWEBKIT_RUBY=off \
-DENABLE_QTUITOOLS_RUBY=off \
-DENABLE_QTSCRIPT=off \
-DENABLE_QTTEST=off \
-DENABLE_PHONON_RUBY=off \
-DENABLE_QSCINTILLA_RUBY=off \
-DENABLE_QWT_RUBY=off \
-DENABLE_SOPRANO_RUBY=off \
-DENABLE_KDEVPLATFORM_RUBY=off \
-DENABLE_KORUNDUM_RUBY=off \
-DENABLE_KHTML_RUBY=off \
-DENABLE_KTEXTEDITOR_RUBY=off \
-DENABLE_SOLID_RUBY=off \
-DENABLE_KROSSRUBY=off \
-DENABLE_PLASMA_RUBY=off \
-DENABLE_QIMAGEBLITZ_SMOKE=off \
../qtruby

Make this command executable and run it
chmod u+x cmake_qtruby
./cmake_qtruby

This should go off prepare your qtruby_build directory for compiling. Once it is finished, you should be able to install by any one of the following methods

RPM-based Install
You will need to have added the include(CPack) to the CMakeLists.txt file as outlined earlier before running cmake. You also now need to install the following:
zypper install rpm-build
zypper install meego-rpm-config # Maybe you dont need this but I installed it anyway

Now all you need to do is run ‘make package’ and then ‘cpack -G RPM’ to build the RPM. You will find that the generated RPM install is called kdebindings-0.1.1-Linux.rpm. That’s because we were originally pulled all our qtruby code out of the kdebindings codebase – you can customize the package name, version and much much more by passing parameters to the cpack command when generating the rpm. You can check what values were used to build the package by viewing the CPackSourceConfig.cmake file. As I was just building this rpm for personal use, I didn’t bother changing any package details. Tut! Tut! Anyway, once you have an rpm you are happy with, simply install the QtRuby bindings on your system via:
rpm -i <your_generated_rpm_name>

Note: If you want to see the RPM spec file generated, have a look at _CPack_Packages/Linux/RPM/SPECS/kdebindings.spec

Deb-based Install (and other package types)
This is pretty much identical to the RPM-based Install. The difference is to use ‘cpack -G DEB’ instead of ‘cpack -G RPM’

Source-based Install
All need to do ‘make’ and ‘make install’ to get the QtRuby bindings installed onto your system. Not quite as easy to undo as an package based installation though!

Testing that everything works
I only tested the RPM package installation method. I found that when running the rbqtapi command I got the following error

/usr/lib/ruby/site_ruby/1.8/i386-linux/qtruby4.so: libsmokeqtcore.so.3: cannot open shared object file: No such file or directory – /usr/lib/ruby/site_ruby/1.8/i386-linux/qtruby4.so (LoadError)
from /usr/lib/ruby/site_ruby/1.8/Qt4.rb:5
from /usr/local/bin/rbqtapi:6:in `require’
from /usr/local/bin/rbqtapi:6

This was because some of the qtruby libraries installed into /usr/local/lib which my MeeGo system does not check for libraries by default. I changed this by adding the file /etc/ld.so.conf.d/qtruby-i386.conf which simply contained the line:
/usr/local/lib
And then running the ldconfig command. Then the rbqtapi command worked happily!

This guide still needs some polish. We’ll get to that eventually, but hopefully it may be of some use in getting the Ruby and Qt playing real nice together on MeeGo!

Developing a simple Match Schedule N900 App for the group stage of World Cup 2010 via Qt on Rails

Thursday, June 24th, 2010

Today we’re going to take a quick look at how to create a N900 app by taking a simple existing Ruby on Rails application and turning it into a Maemo app using Qt on Rails. The main thrust of this blog post is to show how you would tweak the skeleton app generated by the Qt on Rails framework into something that might be useful in the real world. The Match Schedule app is very basic and only shows the upcoming fixtures for the day. But most iPhone apps are simple thin wrappers around a data layer anyway; and this is really only a proof of concept app, so I’d don’t feel to guilty about my humble achievement.

When the World Cup kicked off, I really wanted to have a schedule app on my N900 and couldn’t find one so hence the motivation. Bear in mind that in 2 days this app will be completely useless as the group stage will be over! Warning: it currently requires a level of technical ability to install this app on N900 as it has no installer. You should check out this related blog post on deploying your Qt on Rails apps on the n900 (Maemo) before tackling this one.

The application (source code) is available for download. Note: I haven’t stripped out unnecessary skeleton code from the application, which would exist immediately after generating the Qt application off the Rails codebase. The unnecessary code is related to Create/Edit/Delete functionality which we won’t need in our simple Match Schedule viewer. I left it in to show the minimum amount of work needed to tweak the generated app into a useful real world program. All in all (blog posts and stuff aside), it took about an hour to do. If I had to do it again I’d imagine it would take less than half that time.

All the following steps are done on your dev machine. At the end of the guide you’ll see how to deploy to your N900.

First we create a Rails app.

rails WorldCup

cd WorldCup

./script/generate scaffold Fixture when:string group:string match:string

rake db:migrate

Then I fired up the web server ./script/server and manually entered the fixtures (stupido! I know!). The ‘When’ field has the date formatted as ‘24/6 – 15:00′.

Next up, we turn the Rails app into a Qt app using Qt on Rails. We are still in the WorldCup directory.

./script/plugin install git://github.com/theirishpenguin/qtonrails.git

./script/generate qtify Fixture

This generates the skeleton Qt app. Now let’s bend it into shape, starting with the UI. From now on we’ll be working in the qtonrails/ plugin directory.

cd vendor/plugins/qtonrails

designer-qt4 app/qdesigns/qmainwindow.ui
Once Qt Designer appears, remove the File menu, Commandlink navigation buttons and Action buttons (by more or less right-clicking on those widgets and deleting)

Then regenerate a Ruby code version of the ui files (every time you change the .ui file using Qt Designer you need to do this)
rbuic4 app/qdesigns/qmainwindow.ui -x -o app/ui_proxies/qmainwindow.ui.rb

./run # or it that doesn't work try: ruby run
Then I got errors :-) . Based on these errors, I changed the following..

From app/qpresenters/main_window_presenter.rb I deleted

connect(@ui.viewButton, SIGNAL('clicked()'), self, SLOT('view_clicked()'))

connect(@ui.newButton, SIGNAL('clicked()'), self, SLOT('new_clicked()'))

connect(@ui.editButton, SIGNAL('clicked()'), self, SLOT('edit_clicked()'))

connect(@ui.deleteButton, SIGNAL('clicked()'), self, SLOT('delete_clicked()'))

connect(@ui.fixturesNavLinkButton, SIGNAL('clicked()'), self, SLOT('fixtures_nav_clicked()'))

connect(@ui.actionQuit, SIGNAL('triggered()'), self, SLOT('close()'))

Now let’s try again.
./run

Hey it worked! Cool! There’s more stuff we could now delete but we won’t as we’re focusing on doing the bare minimum.

In order to allow a column to be correctly resized and to provide row select behaviour (as opposed to having individual clickable cells), I added the following line just before the end of the initialize() method in app/qpresenters/main_window_presenter.rb

@tableview.resizeColumnsToContents()
@tableview.setSelectionBehavior(Qt::AbstractItemView::SelectRows)

The resizing of columns to fit their contents will probably become the default in a future Qt on Rails release.

Due to silly bug in Qt on Rails that tries to pull an unnecessary KDE library into generated applications (Issue 2 on the GitHub Tracker), we need to remove the line require 'korundum4' from vendor/plugins/qtonrails/app/ui_proxies/qmainwindow.ui.rb and vendor/plugins/qtonrails/app/ui_proxies/fixture_qform.ui.rb

In order to display just today’s fixtures, we can change the index action in app/qcontrollers/fixtures_controller.rb (again under the qtonrails/ plugin directory)

def index
accept_current_fixtures_from Fixture.all
end

… and add the private method

def accept_current_fixtures_from(fixtures)
fixtures.reject do |fixture|
dt = fixture.when.split(' - ')[0] # Get date from string
date_args = (dt.split('/') + ["2010"]).reverse.map &:to_i
Date.new(*date_args) < Date.today
end
end

Note: The application source code available has the accept_current_fixtures_from() call commented out. This is because once the World Cup group stage is over in a couple of days the list of fixtures would be empty. I have decided that the value of this app as a useful demo in future outweighs the needs of my users over the next two days :-) . In the source code you can simply add the call back in yourself if you wish.

Finally, we make the grid readonly. Because it was late when I did this, I skipped any fancy meta-programming and simply reopened the QtrTableModel to do so. Add this to config/environment.rb

class QtrTableModel
def flags(index)
return Qt::ItemIsSelectable | super(index)
end
end

Phew! Done! To deploy the app to your N900, read the instructions at deploying your Qt on Rails apps on the n900 (Maemo).

Well, hopefully you’ve gotten a flavour of how to use Qt on Rails in a simple real world N900 app. If you’ve any feedback then please get in touch! Until the next time, enjoy the World Cup and I hope your country does well!

Deploying your Qt on Rails apps on the N900 (Maemo)

Monday, June 21st, 2010

Qt on Rails is a framework to let you turn your Rails sites in desktop applications and harness the power of Ruby! It’s not at production level yet but it’s certainly possible to have a good play with it and a bit of a hack! If you’re not familiar with Qt on Rails then a good place to start is this blog post covering the v0.1 release. Also, check out the github repo for more info on installing Qt on Rails on your desktop and building an application with it. Here we show you how to deploy Qt on Rails based apps on your N900. One of the goals of Qt on Rails is to provide an easy way for you to develop apps faster for Maemo and, down the road, hopefully MeeGo too!

Note: This blog post may help you figure out how to install any QtRuby application on the N900, not just Qt on Rails apps. Also, this QtRuby Maemo wiki article was particularly useful when I was stumbling along this path!

One thing you will need to install as part of this guide is Easy Debian. Easy Debian greatly expands what you can do with your Maemo device. It basically sticks a full-featured version of Debian on your device. This means 2 things – firstly, for the uber-geeks out there it let’s you fire up a Linux desktop on the N900; though it’s important to note that your normal Maemo desktop isn’t affected by Easy Debian. Secondly, having a full-on Debian available let’s you run Linux apps such as Open Office! Sweet! And what rocks is that you can even run these programs without invoking the Easy Debian Linux desktop – in a seamless manner. It’s important to note that the user interface to these Easy Debian-based apps behave a differently to a typical native Maemo program; rather they work like a traditional desktop application with a mouse pointer on screen.

Install Steps
  • Note: For simplicity, this guide assumes you are installing an application which stores data using sqlite3. Also, the steps here have been tested against the N900 firmware update PR1.2. If you are using an older version of the firmware you may want to consider updating it.
  • Firstly, install Easy Debian with the N900’s Application Manager
  • Install the Easy Debian image via the new Deb Img Install application added to your list of applications
    • Note: This is a 1 gig download, but comes with cool stuff like OpenOffice and intergrates pretty seamlessly with your desktop
    • Takes an hour or so to download and then extract itself
  • Open the Debian Chroot terminal (not the usual N900 terminal), which should now be in your list of applications
  • Install rubygems, qtruby and  sqlite3 with ruby bindings
    • sudo apt-get install rubygems
    • sudo apt-get install libqt4-ruby
    • apt-get install libsqlite3-ruby
  • Install the bits we need need from Rails (without installing documentation)
    • sudo gem install activerecord activesupport activeresource –no-ri –no-rdoc
  • Zip up your Qt on Rails application and copy to any directory on to the N900. Note that the Qt on Rails application consists of the entire Rails directory directory including the vendor/plugins/qtonrails directory intact and  a sqlite3 database already created under the db directory).

    If you don’t have your own Qt on Rails application to hand then you can create the RadRadio app discussed in the “Make it so, Jim!” section of the v0.1 release blog post

    In the Qt on Rails v0.1 release there is a bug that accidentally introduces a dependency on a korundum library, which is not needed in this case. An issue is logged against this in the Qt on Rails Issue Tracker As a workaround, find and remove any occurrences of require 'korundum4' in files under the vendor/plugins/qtonrails/app directory

  • Once transferred, simply unzip it on your device. Note: If you saved the zip to the Documents folder on your N900, this can be found under /home/user/MyDocs/.documents when poking around the filesystem
  • Finally, via the good ol’ Debian Chroot terminal, change directory to the vendor/plugins/qtonrails directory of your app and execute

    ruby1.8 run

  • Boom! You should see your Qt on Rails app in all it’s glory!

Note there is a bug where you cannot input into a text field when running a Qt on Rails app on the N900 using above technique (seamless mode). As a workaround, open the Qt on Rails app inside of the Debian LXDE desktop (rather than in seamless mode). You can find Debian LXDE in the list of applications on your device. Inside Debian LXDE, open a terminal and run the application as above. Just a quick heads up, sticky keys don’t work like you’d expect – you have to hold down the Shift and Fn keys to use them.

Qt on Rails v0.1 released. But is this Ruby-based Qt and KDE app framework doomed?

Monday, June 21st, 2010

Ruby has changed the way developers build web applications. Since popularised by the Rails framework, programmers no longer stumble around in the dark with disparate web forms; instead they are able to clearly focus on the business problem and expose a well-modelled domain in a easily testable manner. Traditionally used in data-heavy domains, today’s web apps now encroach on the desktop’s home turf of rich highly-functional applications – something years ago thought impossible. And most surprisingly, through clever use of patterns and conventions, they’ve arguably become the easier of the two to develop. Given this, could desktop developers learn from the web app approach? This is in part the motivation behind Qt on Rails – let’s use a conventions-based approach to building desktop applications and clients. Let’s harness the ease and expressiveness of the Ruby language. And let’s have a clean consistent domain model underneath the hood with a comprehensive suite of tests to boot. A grand idea; but right now, it’s on course to fail…

List Page - Disc Jockeys
Main window listing Disc Jockeys (Click the image to enlarge)

What does this framework look like?

What exactly is Qt on Rails? Well first, let me just make a little guilty admission. This blog post is aimed at Ruby and/or Rails developers first, then Qt/KDE developers second. This is not because I believe one camp is more important than the other. It is because I really want to bring Rails dev’s on-board to KDE/Qt development and I see a real need to give them a first-class Qt toolkit; to make desktop apps as brilliant and easy to develop as their web apps. If Qt on Rails ever makes it as far as being a fully mature framework, I hope that a Rails developer using it for the first time will find it a very familiar experience. The directory structure, naming conventions and overall architecture (to date at least) has been chosen to that end. But I hope to do an article focusing on approaching this project from a more on Qt/KDE perspective. So what is Qt on Rails like?

Well, imagine you just wrote a Rails web application. You’re finished! Let’s say we just built a web app for a fictional company called RAD Radio. We have two important things in our system – Disc Jockeys and Sponsors for the radio shows. So we have this really neat model layer sitting on top of our database. It handles all our business logic and things like validation of data being persisted – let’s reuse this… verbatim! This is our line in the sand! Design choice 1, Qt on Rails literally reuses everything from the model layer down already within your Rails application!

If we start from the front end of our proposed desktop application and work backwards, we want to have a Qt app which consists of various different screens, some of which may be on display simultaneously. This is a little different from the web, because generally on the web you can think of having just one screen and this gets blown away on each request (unless AJAX intervenes, but still you get the overall point). In a Qt desktop app we decide that our initial screen is to be “main” window for our application. Clicking on a button may cause a new window to launch, for example, a window to edit a Disc Jockey’s details, but the main window will remain there, though not active. This kind of difference (from your typical web behaviour) presents a difficult challenge and will have a big effect on our architecture – for example, it has influenced my decision not to try and reuse anything for the controller layer generated in a Rail’s application. Back to our story, we have a main window as our starting point, which you can see in the figure above. It should have a way to navigate between different parts of your application. This is achieved through the big command link buttons at the top of the window. In our web application, each part of our application is based on different sources of data (called resources when using RESTful terminology). Clicking on the Sponsors command link button would cause the grid to be refreshed with Sponsor records. And then clicking on the Disc Jockeys command link button refresh the grid with Disc Jockey records again.

This sounds reasonable so far. A quick side note though; bear in mind this is still early days for Qt on Rails. I’m sure many good KDE and Qt developers may be horrified at the UI decisions made above. I’m not a Qt or KDE expert! This is another big challenge. One of the most crucial areas we need help on is getting feedback on how Qt and KDE applications are generally laid out, what widgets are used for what purposes and so on. In essence, what are the best practice guidelines for HCI in something like KDE and how can we incorporate that into the apps we generate with Qt on Rails.

So we are looking at the main window, which contains a list of Disc Jockeys in a grid – how does this work? Well, first we need to be aware of what Qt is giving us here. The list widget that you see on screen is a Qt widget called a QTableView. It is concerned only with displaying stuff. Underneath that we have a QAbstractTableModel. This holds the data, it does not care about how it will be displayed. Now it’s worth pointing out that a QAbstractTableModel has nothing to do with the Rails concept of a model. You see, the Qt folks have used the MVC pattern in their architecture for donkey’s years now; and it’s important to not confuse the two different uses of the same paradigm. The QAbstractTableModel is an object into which you stick a whole bunch of Rails records that you wish to display in a list. We then plug the QAbstractTableModel into the QTableView widget and that’s how your records are displayed. It’s also important to note that when a QTableView sees the QAbstractTableModel being plugged in – it has absolutely no idea that the underlying records are of type Disc Jockey. Think of the QAbstractTableModel as an adapter between a collection of records for a particular Rails model and the QTableView widget which will ultimately display them. Probably most importantly, remember that

  • A Rail’s model equates to one record
  • Whereas a QAbstractTableModel equates to many records – it sits on top of a collection of Rails records and allows them to be displayed in something like a QTableView widget

Note: The Qt API is incredible. It’s extremely comprehensive! Check it out at http://doc.qt.nokia.com You will want to look at the “C++ Application Development Framework” for the version of Qt you develop with. One big tip to note down – where it talks about something like a QAbstractTableModel in the docs – is that it is referring to the C++ world. In your head just translate this to Qt::TableModel – now you can happily use all the documentation available. Also, in your code you will always write Qt::AbstractTableModel, never QAbstractTableModel.

So to edit a Disc Jockey record I select a row and click the Edit button near the bottom of the page. Hey presto! An Edit Disc Jockey form appears…

Edit Form - Disc Jockey
Form for editing a Disc Jockey (Click the image to enlarge)

Nice! And when you click the Save button the Edit form is dismissed and the list of Disc Jockeys in our main window is refreshed!

Cool! But where do all the Qt on Rails files live?

Qt on Rails is installed in the vendor/plugins directory of your Rails app (see http://github.com/theirishpenguin/qtonrails for more details on how to install). Under vendor/plugins/qtonrails/ there is a directory called app/ which holds the Qt application code. In turn, app/ is divided into the following subdirectories, with each subdirectory corresponding to a layer in our application framework, listed here from the highest level (like the HTML stuff in a web app) to the lowest (the controller in our case – as everything from models down to db is handled by vanilla Rails).

  • qdesigns – XML markup files (with a .ui extension) which are to Qt screens/widgets what HTML files are to HTML pages/elements
  • ui_proxies – A Ruby representation of .ui files – this is an autogenerated layer which you don’t really need to worry about
  • qpresenters – Where the presentation logic (not any business logic) for your screen lives
  • qhelpers – A place to put logic that you wish to reuse across presenters
  • qviews – Where we decide exactly how we will build a view for a particular controller action (I accept that the name ‘qviews’ is confusing; maybe ‘qviewbuilders’ would be better or something totally different)
  • qcontrollers – Where we decide what data to retrieve for a particular action (though we don’t specify ‘where to go’ in the way a Rails controller has render() or redirect_to() methods)
I am the Executioner…

So here’s the flow of control. In our vender/plugins/qtonrails directory we have a ‘run’ command. When we execute it, the command…

  1. Fires up a Qt Application instance
  2. Asks our (very primitive) Router to take a given route and instantiate a QView and a QController for it
  3. The QController then fetches data depending on the action (just like a Rails action) and hands off the data to the QView
  4. The QView then decides what screen should be build (or whether to stay on the same screen and perhaps just refresh a list of records)
  5. Once the appropriate Screen has been built, it is displayed with a show() call. At this point the user will then see something happen on-screen.

The above is pretty much like one request-response cycle in a Rails app. Now we play the waiting game

  • The user does some*thing like selects a row and clicks the Edit button.
  • At this point the QPresenter comes into play. The QPresenter is your window widget. I didn’t tell you then, but the QPresenter was created earlier in the QView layer when we call the constructor for the window (ie. the QPresenter) we wish to display). I’m open to the fact that QPresenter may not be the best name for this! Anyway, the QPresenter contains your presentation logic. In our case, the user has just clicked the Edit button on the MainWindow presenter. This causes the handler for the event – the edit_clicked() slot to be called. Qt uses a brilliant concept called Signals and Slots to handle events in your application – a Signal is something that acts as a trigger (such as a button being clicked) for a Slot; a Slot simply being a function dedicated to doing something useful in response. A Signal is connected to a Slot using the aptly named connect() method. I neglected to bore you with this little detail earlier but this connection was carried out in the constructor for the QPresenter (ie. the window) which took place a few steps back when we mentioned that the QView layer decided what screen is to be built
  • Finally, the slot – edit_clicked() in this case – asks the Router to take a given route and now we’re back to step 2 of the flow of control outlined earlier
  • Phew!
Make it so, Jim!

So that’s it in a nutshell. How do get all this lovely goodness to turn your Rails web app into a skeleton desktop app? One command, mon ami! From the root of your Rails directory simply run

./script/generate qtify DiscJockey Sponsor

So let’s say you have no Rails app right now. Here’s how to get to a basic web app and skeleton desktop app in double quick time!

Firstly, just a quick note on OS dependencies. Qt on Rails has mainly been developed to date on Kubuntu 9.04, Kubuntu 9.10 and the Ubuntu Netbook Remix 9.10. For these platforms, you can install the packages mentioned in the “First Install the appropriate packages” section of this Developing Qt4 Applications using Qt Designer and Ruby on Kubuntu article, which also goes into more detail on QtRuby development if you’re interested. This QtRuby bindings article on the KDE TechBase also gives some useful info on the Ruby bindings for Qt.

We’ve not tried this yet on Windows or Mac, but here’s a Windows QtRuby install guide by Richard Dale and a QtRuby on the Mac install guide. So you are welcome to try and install QtRuby on one of these platforms but we can’t promise anything!

Perhaps, most excitingly of all, Qt on Rails apps can be deployed to Maemo devices such as the N900! Check out this related Deploying your Qt on Rails apps on the N900 (Maemo) article! And MeeGo support will surely follow sometime soon!

Ok, let’s cook you up a Rails app. Here we are using Rails 2.3.5 and assuming you are at a Linux command line (see Qt on Rails github project page for more installation details of Qt on Rails itself)…

rails RadRadio

cd RadRadio

./script/plugin install git://github.com/theirishpenguin/qtonrails.git

./script/generate scaffold DiscJockey name:string date_of_birth:date programme_name:string radio_slot:time max_num_guests:integer next_review:datetime

./script/generate scaffold Sponsors name:string signed_up_on:date

rake db:migrate

./script/generate qtify DiscJockey Sponsor

cd vendor/plugins/qtonrails

./run

# If ./run on it's own gave you a permission error you can try 'ruby ./run' instead

# Oh yeah!

What you see is almost what you get…

Hopefully, you should be seeing an app around about now. Once you have some rows in the list of disc jockeys or sponsors (create some DJs using the New button), you will see that cells of the grid that make up the list can be edited in-place. This is quite a powerful feature to have out of the box. An Edit button is provided also, though if you plan to provide an Edit button to your users, which launches a form, then you should probably make the grid read-only so as not to confuse them by having two ways of editing. As this is a early prototype of the framework, I’ve left the Edit button and in-place editing enabled, trusting you to tailor them to your app’s needs. If you were going to switch off in-place editing you would probably also want to select the entire row (rather than just one cell) when you click on a cell in the row.

Let’s have a quick look at form validation in action. Add a validates_presence_of validator to your DiscJockey and Sponsor Rails models so that they look as follows

#In app/models/disc_jockey.rb (under root of your Rails app, not under qtonrails)

class DiscJockey < ActiveRecord::Base
validates_presence_of :name
end

#In app/models/sponsor.rb (under root of your Rails app, not under qtonrails)

class Sponsor < ActiveRecord::Base
validates_presence_of :name
end

Close and restart the RadRadio Qt on Rails app. When you hit the New button and try to create a new Disc Jockey or Sponsor without a name, you will see that the Rails model validation kicks in and you get a validation message telling you that you need to correct the name field. Validation also works if you are editing a record after clicking the Edit button, however validation messages don’t appear if you edit a record in-place in the grid (just because I haven’t had a chance to implement that yet).

Again, as it’s an early release there’s also plenty of bugs in there, such as a crash if you try to click the Edit Button without selecting any row. A list of issues is maintained on the Qt on Rails Issue Tracker. Check it out to see what limitations currently exist and add to it if you spot a new problem!

Doomed?

As you can see, this codebase is being opened up quite early. A good start has been made – but the project is still very embryonic! Surely, it’s a bit early to be talking about doom? Well, unless hacking on Qt on Rails appeals to some developers out there it will certainly die a merry death on the great scrapheap of nice projects that just didn’t make it. Why? Not only is there a lot of work that needs to be done, but also it’s more fun to work on the project when there’s a crew involved, which also brings new ideas and energy to any project. Otherwise it’s unsustainable.

But life wouldn’t be fun it it wasn’t a bit of a challenge, right? If you think this kind of project might interest you, if you’re not put off by insurmountable odds, then know that your framework needs you! Drop me an email at declan [[AT]] weuseopensource [[DOT]] com or twit a quick tweet on twitter (theirishpenguin). The Qt on Rails Issue Tracker is a good place to start looking for things to hack on. Or you’re welcome to fork the project on github and develop that killer feature you’d like to see in there!

Qt on Rails, because it’s at an early stage, is an easy place to start – there isn’t lots of code to weigh you down. The framework itself is very thin, the majority of the code is actually Rails style generators to take the Rails model layer and build the Qt/KDE app on top of it. Because of the tiny codebase, it shouldn’t be hard too get your head around what’s going on.

Qt on Rails doesn’t want to be doomed!

It’s intended that Qt on Rails gives Ruby and/or Rails developers an outlet to develop first class desktop apps using the best available framework. Rails developers often ask, “If I want to build a great cross-platform desktop app, what GUI toolkit would I use?” The answer varies and there no one headline GUI toolkit/desktop framework that currently has mindshare amongst Ruby developers and works great across multiple platforms. Given that Qt is currently so strong across the Linux desktop, commercial Windows applications, Macs and mobile platforms such as Maemo and MeeGo why shouldn’t it be the first thing you reach for when building a Ruby desktop app? Come help us build Qt on Rails! Stave off the doom!

A Ruby Module that mixes in Class Methods (static) and Instance Methods

Thursday, February 4th, 2010

Ho ho, this one can catch you out more than once so it’s high time to write a blog post to cover this off. Turns out it’s a commonly used pattern to the rescue. Thanks to eoin on #ruby.ie for pointing to the solution on RailsTips.org.

Here’s quite a tasty diagram too for easy reference.

module Swingable

    def self.included(base)
        base.extend(ClassMethods)
    end

    def instance_swing
        puts 'Did an instance swing!'
    end

    module ClassMethods
        def static_swing
            puts 'Did a static swing!'
        end
    end
end

class BaseballBat
   include Swingable
end

BaseballBat.static_swing
BaseballBat.new.instance_swing

Santa’s got Gems baby! Ruby Ireland Christmas Meetup 2009

Friday, December 18th, 2009

Ho ho ho! The month’s Ruby Ireland meetup sprag right out of the traps with early adopters showing up at 6pm in the lobby area of the Trinity Capital Hotel, Wed Dec 16th. Easing into the evening with a 4 euro pint and talk of Android phones – seemingly the top item of everyone’s Christmas shopping list – the latest crop of gems in the Ruby world was in hot debate, gemcutter in particular.

A couple of folks had been playing around with RubyGame for visualising data as it changes on the fly – showing that this framework is for more than just gaming. The XML/HTML parser Nokogiri was also mentioned a few of times in passing, with the particularly eye-catching quote “XML is like violence – if it doesn’t solve your problems, you are not using enough of it” adorning the home page of its website. And the cracking little tool tig was also brought up, which has a dinky little ncurses interface into git repositories. Pretty cool; not least because it makes it easier for newbies to avoid being bitten when they start git’tin.

The downstairs lobby in the hotel worked out great for people to meet up and relax, with most people turning up at the scheduled 7 o clock for kick off. From there we took over the, what has to be said, pretty classy meeting room complete with old style couches and some Joan Miró paintings. Just in tune with the creative buzz we had going on. There wasn’t too much talk of Ruby for a while as most people were in stunned admiration of the room. Then the food platter arrived. Impressively, this is when everyone showed off their good manners by looking shyly at the platter for a few minutes, with that kind of “You first, sir” glint in their eye, before taking the plunge and sinking into the pakoras and wedges! Pretty much undoing any good work in the gym from earlier in the day!

One of the funnier moments of the night was when someone went to check the tweets against the (now settled upon) #rubyireland hashtag. Only to find lost rubyists tweeting from the hotel lobby as to where the meetup was on. After a quick runaround the lobby to herd anyone wielding a Macbook into the meeting room, the evening was back on track. We split up into a few smaller groups, with the main walk-through being on the qtonrails – a Rails plugin to simply developing applications on Linux and other platforms using Nokia’s Qt framework atop Rails.

To finish off we had a bit of improv comedy from everyone at different closing stages of the evening; in particular Paul O’Malley with his faithful rendition of an emotion beekeeper. And yes now we’re straying off topic so it’s probably time to go. We’ll leave you with Paul’s write up of last night’s shenanigans :-)

Thanks to everyone who showed. Have a great Christmas and catch ye all in Jan 2010 – surely destined to be the decade of Ruby domination!

Ciao,
Dec

Generate Rails Migrations from your PostgreSQL or MySQL database

Thursday, November 26th, 2009

1) Create a new empty Rails project called schemer

2) In your config/database.yml file, point at the database you wish to dump to a migrations file

3) Run the command ‘rake db:schema:dump’. This should create a db/schema.rb file. Amazingly this effectively is your migrations file!

4) To tidy up create a file called file db/migrate/20091125205635_create_initial_schema.rb

5) Then copy the create_table statements from the schema.rb file into the new file 20091125205635_create_initial_schema.rb. Here’s a template

class CreateInitialSchema < ActiveRecord::Migration

  def self.up
    # Put all create_table statements from schema.rb file here
    # Note: You don't need the 'ActiveRecord::Schema.define(:version' line or it's enclosing end statement
    # ...
    # ...
  end

  def self.down
    # Don't really need this
  end

end

6) Once you’ve all this done you can just run ‘rake db:migrate’ and you should have a new sqlite db up and running under db/development.sqlite3

Thanks to Justin Ball on this Nobody Listens Anyway blog at Dump an Existing Database Schema Into a Ruby On Rails Migration Ready Format for the basis of this tip. Sometimes somebody does…

Understanding how Ruby stores objects in memory – the Ruby Heap

Thursday, October 29th, 2009

Ruby has it’s own heap management which actually consists of several ‘Ruby Heaps’ to manage objects created during the execution of a Ruby program; this is separate from the System Heap for your Operating System. Each individual Ruby Heap contains Slots, with each Slot able to one reference one object.

The entire space that an object takes up in memory ***is not stored inside the Slot***. Rather each Slot is a small fixed size space which can be thought of as the Ruby interpreter’s handle a location in memory. This location exists outside of the Ruby Heap itself and contains the real ‘meat’ of the object. To be clear, if you have a 50MB string – the 50MB of data is stored outside of Ruby’s Heap. If you really want to know the story of the 50MB, the space for it is actually allocated by something like the malloc command in C (as good ol’ Ruby is written in C) and then stored on the System Heap. The Slot in the Ruby Heap simply contains a reference to that memory location on the System Heap which contains the 50MB of data.

Here’s an example. Let’s say that a Ruby program creates a single string of 50MB
* A single free Slot in a Ruby Heap becomes filled
* Memory to store the 50MB of data that makes up the string itself is allocated in memory and put on the System Heap (outside the Ruby Heap!) and a reference to this location is stored in the Filled Slot on the Ruby Heap
* There comes a point in time when this string is no longer needed. This slot is garbage collected on the next GC iteration
* The Filled Slot is turned into a free slot. The 50MB of data in memory referred to by the slot is also freed and returned to the Operating System

Ruby starts of with a minimal set of Ruby Heaps. These are managed by by a Ruby Heap list. Ruby creates Ruby Heaps when needed and frees Ruby Heaps back to the OS when no longer needed (the latter is done in a sub-optimal manner – more on this later). Each Ruby Heap created will be 1.8 times the size of the previous heap. In other words, it will contain 1.8 times the number of slots of the previous heap. Ruby’s Garbage Collector, periodically iterates through the Ruby Heaps and frees up any Slots as appropriate (and also the memory that an object really occupies which is referenced by the Slot – ie. the 50MB data of the String) back to the system. Once a GC iteration is complete, some of the Slots that were filled will now be empty – known as Free Slots. Remember that we said that Ruby’s Heap management actually consists of many Ruby Heaps. Well if one of these Ruby Heaps consists of only Free Slots then the Ruby Heap itself will be freed back to the Operating System.

There is a problem with this last statement however – if a Ruby Heap contains mostly Free Slots and one Filled Slot then it will not be freed. You could have many Ruby Heaps in this state. As long as a Ruby Heap contains even one Filled Slot it will not be returned to the Operating System. It just takes one bad apple to spoil everything! What would be nice is if some sort of Heap Compaction (kind of like disk fragmentation) took place where all Filled slots were pushed together into completed filled Ruby Heaps. This would leave you with completely filled Ruby Heaps, one semi-filled Ruby Heap and then a bunch of completely empty Ruby Heaps. The completely empty Ruby Heaps could then be freed, releasing precious memory back to the Operating System. Alas the current mainstream Ruby interpreter does not do this.

References
* How the Ruby Heap is Implemented Phusion Passenger’s Hong Lai gives a great explanation of the Ruby Heap – the banner may not be quite suitable for work. Fortunately, there’s a censor button :-)

* Fine tuning your garbage collector Chris Heald explains some of the settings around garbage collection

* Ruby’s Garbage Collections effect on Ruby on Rails Pluron Inc’s blog discusses so of the knock-on effects of Ruby GC on Rails and importantly mentions the 8 MB memory allocation tigger for the garbage collector

Bleak House – A Tool for measuring Objects in Memory for a Ruby Program

Wednesday, October 28th, 2009

Bleak House is a tool that tells us
- How many Slots there are in total at a point in time in a Ruby program
- How many Slots in total are filled
- How many Slots in total are empty (free)
- How many Filled Slots can be attributed to a particular line of code

Bleakhouse can be used to tell you if program is holding on to objects that it should be relinquishing. But it doesn’t tell you how much data is stored in memory for the ‘meat’ of the object (ie. that 50MB of data in a 50MB String). Just because you know there is a Filled Slot exists – you don’t know if the data in memory that correlates back to that Slot is 1MB, 10MB or 100MB.

However, if you repeat a series of a specific set of operations a small number of times, measuring with Bleakhouse, and then restart the server with Bleak house and repeat the operations a large number of times and see a big difference in the number of filled slots can tell that your program is holding onto objects (references) that it should not. Of course, if your program is supposed to keep hold of an increasing number of references (such as a global variable or a singleton that keeps accumulating references for the duration of your program) then this would be expected. Though you might want to double check your design. You will be able to see the cause of the problem from the detailed breakdown of which lines of code were the biggest offenders in terms of creating objects. If you see a large number of free slots (relative to the number of filled slots) then this means that at some point in your program a lot of objects existed (possibly due to a spike in application usage) but then reduced.

Does the free slots count matter? Well, yes because there is an memory overhead due to each free slot that exists – how much depends on your particular system. If your system has a slot size of 20 bytes then every one million free slots costs you an additional 20MB that is not being utilised. This becomes a problem if your application is subject to large but infrequent spikes in the number of objects that exist within your program a particular moment in time because the free slots are taking up significant amounts of memory even when your application is twiddling its thumbs between the spikes.

Simple straight up caching for pages served by Heroku

Wednesday, September 16th, 2009

So you’ve got an app that’s ticking along nicely; being served up a good steak in a 5 star restaurant – but you’d like to boost it’s performance with some caching. For those who develop their apps on the Heroku platform, a great way to do this is to cache a dynamic page using Varnish. This means that your page is served up super fast without hitting Rails/Sinatra/whatever. And best of all it requires no extra gems or anything, just a well placed one-liner in your controller.

Firstly, you can only use this technique if all users that visit this page expect to see the exact same content – in other words you have no ‘per user’ customised content on a page. To help understand how this type of caching works, imagine that the first time your page (let’s say an Events index page) is hit it is turned into a static html page for a pre-defined amount of time (let’s say 60 seconds). Anyone else who visit this page (ie. anyone else who visits this particular controller action) during the next 60 seconds gets that static html page. After the 60 seconds the static html page is removed from the cache. Thus the next hit will cause your underlying dynamic page to be invoked; then the caching process kicks off again lasting another 60 seconds. And so on and so fourth.

With the increasing amount of web applications that call APIs, such as Twitter’s API, this is a really easy way to ensure that you do not end up spamming a service provider with an unreasonable number of calls per hour. This is the technique we use on www.thelisbontweety.com to keep our API overhead down.

So how do you do this? Simply put something along the lines of

response.headers['Cache-Control'] = ‘public, max-age=60′

as the first line of your action for the page you wish to cache. The max-age setting means that this will be cached for 60 seconds. After you put this in your application and redeploy to Heroku, you can see if it’s working by using http://hurl.it

Just enter the  URL for your action and click Send. You should see something like “Cache-Control: max-age=60, public” in the output if it’s working.

And that’s it! No need to install anything. Just cache your little heart out with Varnish. Top marks to chaps at Heroku for making this so easy to use out of the box at Heroku. For more on this technique check out their HTTP caching docs at http://docs.heroku.com/http-caching