Archive for September, 2008

Who has experience with Qt 4 on OS X?

I’ve had pretty bad experiences with wxWidgets. Not that the toolkit itself is bad, but it’s lacking functionality and polish in various unexpected and awkward ways. The biggest turn-off for me is that it doesn’t support buttons with icons. Not only do I want my GUI apps to work well, I also want them to look nice and to integrate well into the environment. On Linux/GNOME, having buttons with icons is almost essential – not having icons just makes the GUI look plain and ugly. On Windows it can make a big difference as well when it comes to UI aesthetics. The wxWidgets developers commented that they won’t implement this because not all platforms (e.g. Windows) support it. I personally think this is nonsense – Delphi has supported buttons with icons since version 1.0 (for Windows 3.1). Besides, why not just implement it on platforms that do support it, and document it as such? This is already the case for things such as the flat button style.

Another thing I don’t like about wxWidgets is how it forces one to build the GUI top-down. One must first construct a parent container before one can construct child widgets. It’s not possible to construct an invisible child widget and then later on attach that onto a parent. This seems to be a design decision influenced by limitations in Windows.
wxWidgets also has the tendency to layout the GUI differently on different platforms. I usually develop wxWidgets applications on Linux, and port them to Windows later on. What usually happens is that the GUI looks fine on Linux, but totally breaks on Windows – buttons being laid out differently, controls that have the wrong size, etc. I usually end up having to fix the GUI code for Windows. Apparently wxWidgets has different layout implementations for different platforms, and they behave subtly different ways.

The list can go on and on. But generally, wxWidgets feels clunky and awkward except for simple and standard user interfaces without a lot of dynamics. The differences in layout and resize behavior on different platforms seem to be bigger than the differences in CSS implementations in different browsers (with the exception of IE of course).

Qt 4 seems to be a good cross-platform GUI toolkit and doesn’t suffer from these issues. It looks very nice on Linux. However, I’ve seen Mac people flaming Qt for looking “totally miserable” on OS X. I couldn’t find any screenshots of Qt 4 on OS X so I can’t confirm whether that’s true. Does anybody have experience with Qt on OS X, and can show me some screenshots?

Comments (9)

Who’s running Phusion Passenger in production?

An interesting thread appeared on the Phusion Passenger mailing list, in which user asked who’s running Phusion Passenger in production. We’re actually very interested as well, seeing as we’re currently building a new website for Phusion. Please drop a note at the mailing list (or here, though the mailing list is preferred) if you’re running it in production as well.

Comments

validates_uniqueness_of does not guarantee uniqueness

Using validates_uniqueness_of in conjunction with ActiveRecord::Base#save does not guarantee the absence of duplicate record insertions, because uniqueness checks on the application level are inherently prone to racing conditions. For example, suppose that two users try to post a Comment at the same time, and a Comment‘s title must be unique. At the database-level, the actions performed by these users could be interleaved in the following manner:

              User 1                 |               User 2
 ------------------------------------+--------------------------------------
 # User 1 checks whether there's     |
 # already a comment with the title  |
 # 'My Post'. This is not the case.  |
 SELECT * FROM comments              |
 WHERE title = 'My Post'             |
                                     |
                                     | # User 2 does the same thing and also
                                     | # infers that his title is unique.
                                     | SELECT * FROM comments
                                     | WHERE title = 'My Post'
                                     |
 # User 1 inserts his comment.       |
 INSERT INTO comments                |
 (title, content) VALUES             |
 ('My Post', 'hi!')                  |
                                     |
                                     | # User 2 does the same thing.
                                     | INSERT INTO comments
                                     | (title, content) VALUES
                                     | ('My Post', 'hello!')
                                     |
                                     | # ^^^^^^
                                     | # Boom! We now have a duplicate
                                     | # title!

This could even happen if you use transactions with the ‘serializable’ isolation level. There are several ways to get around this problem:

  • By locking the database table before validating, and unlocking it after saving. However, table locking is very expensive, and thus not recommended.
  • By locking a lock file before validating, and unlocking it after saving. This does not work if you‘ve scaled your Rails application across multiple web servers (because they cannot share lock files, or cannot do that efficiently), and thus not recommended.
  • Creating a unique index on the field, by using ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the rare case that a racing condition occurs, the database will guarantee the field’s uniqueness.

    When the database catches such a duplicate insertion, ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid exception. You can either choose to let this error propagate (which will result in the default Rails exception page being shown), or you can catch it and restart the transaction (e.g. by telling the user that the title already exists, and asking him to re-enter the title). This technique is also known as optimistic concurrency control.

    Active Record currently provides no way to distinguish unique index constraint errors from other types of database errors, so you will have to parse the (database-specific) exception message to detect such a case.

I’ve just contributed this documentation to docrails, so you’ll see it in Rails 2.2′s validates_uniqueness_of API documentation.

Comments (14)

wiki.rubyonrails.org was down

Today wiki.rubyonrails.org was briefly down, for like 30 minutes or so.

I thought it might be a problem in Phusion Passenger, seeing that the wiki is running on it. I wanted to the restart Apache, but I decided to look in the wiki log files before doing that.

It turned out the server ran out of disk space. I truncated the Apache log files, which were consuming 40 GB or so. After that, everything went back to normal.

Comments (2)