First off, I would like to say that Ruby is the simplest language to
learn.  Not just the language, but the libraries too.  You could have
learned Ruby in less time than has been spent debating it's merits on
this forum.

More to your question though.  Ruby has some areas that it is
extremely good at, and some it is not so good at.  Ruby's execution
speed is much slower than "C".  Depending upon the task maybe 300
times slower.  You can't do video processing at 30 fps in Ruby.  It is
more like 1 frame in 30 seconds.  Ruby's speed though is about the
same as other interpreted dynamically typed languages.

Many tasks will be outside the scope of Ruby's built in library, and
you will need bindings to "C" libraries.  For example you might desire
a binding to the Win32 API.  There is a partial binding available, but
it does not cover all 90,000 API calls.  This is a problem with every
language in existence except "C" and C++.  I believe the lack of such
bindings and the lack of documentation for such bindings is one of the
main reasons "C" and C++ continue to live on.  Plus "C" and C++ do not
make many comprises when it comes to execution speed.

I wanted to write a Publish & Subscribe server in Ruby.  I discovered
that Ruby does not have asyncronous socket support under Win32.  So, I
wrote it in Python.  Python has a really great asyncronous socket
interface.  This turned out to be slower than I had hoped, however. 
After experimenting some in "C", I found it to be at least 300 times
slower.  I did not want a slow Pub/Sub server.  I suspect most people
do not want slow libraries.  Thus, most libraries are going to be
written in "C".  Ruby will always require bindings to these libraries.

I since discovered that cross platform socket libraries are not easy. 
Most of these use Win32s copy of the unix calls, select/read/write. 
This turns out not to be nearly the best method on Win32.  On Win32
you want to use Overlapped I/O and Completion Ports.  This is so
different from the Unix way that I don't think a common interface can
be created.  All languages that I am aware of that have socket support
built into them, attempt to have cross platform support, and they
attempt to do it by mirroring the Unix API on Win32, which is just not
efficient on Win32.  The Win32 method is more efficient than the Unix
method besides.

Ruby does not have a binding yet to WxWindows (A cross platform GUI). 
One is in the works.  Python has a binding to WxWindows. However, you
have to read C++ documentation to know how to use it.  A less than
optimal solution.  I believe the binding to be a partial one with no
documentation stating where it is incomplete.

Ruby has a partial binding to the Win32 GUIs, documented in Japanese.

As it turns out, I am beginning to think the notion of a
cross-platform GUI is flawed to begin with.  At least it is not
optimal.  It may be satisfactory for some types of work.

I want a language that is as fast as "C" or nearly so, that has a
great GUI library and a great socket library that runs on Win32,
Linux, FreeBSD, and OS/X.
I want the language to be as easy to program in as Ruby.
Such a language does not exist and I have looked hard.

I think "C" and "C++" are used so much because every other language
has flaws when it comes to speed or library support.

Other possible alternatives are LISP/Haskell/Ocaml.
Ocaml is one of the faster languages.  It is sometimes only 2 times
slower than "C".  For me, that factor of 2 is enough to kill it for
almost all tasks.  And if the factor of 2 does not matter, then a
factor of 300 might not either and Ruby comes back into play.  Ocaml
is hard to learn.  Ocaml has a big sandbox of tools.  It is on my list
of things to learn better.

Haskell has a cleaner syntax than Ocaml.  Haskell implementations are
not very fast yet.  Haskell is maybe 4 to 20 times slower than "C". 
Haskell lacks library support.  Haskell is hard to create "C" bindings
for.  Haskell has some really cool features though.  I tried to use
quick sort with HUGS to sort 20,000 elements.  It overflowed the
stack.  Recursive quick sort implementations also blew Ruby and
Python's stack.  Java handled it.

LISP.  I know for many people LISP is the world's greatest language.
LISP essentially has no syntax.  Some people think this is one of
LISPs greatest features.  I personally despise it, for this reason.

LISP/Haskell/Ocaml all make a person think recursively to solve all
problems.  I don't think this is natural.  It is natural for some
problems, but not all.

Java, C#, and Visual Basic all fall into the same category for me. 
Slower than "C", faster than Perl/Python/Ruby.  Actually, I am not
sure about VBs speed, but it can be compiled to native instructions so
I am guessing here.  They have a sandbox of tools.  If you have to go
outside the sandbox, life gets hard.  I don't recommend Java for GUIs.
 C# and VB are Windows specific.  All of these are easier to get work
done than "C", but not as easy as Perl/Python/Ruby.

Most all other languages are too experimental at this point.

Well, those are the choices in a nutshell.  So, it depends upon what
you need to get done and if that task is doable in the sandbox of
tools available to the language and if the speed requirements can be
handled by the language.

The "D" language looks interesting.  It is very new though.  I fear
that if  Walter Bright gets hit by a car or something the language
will disappear.

I just thought of one other observations.
Typed languages vs. Dynamically typed languages.
This is a religious war of course, but I just the wrote the following
today
in C++:

_cb = auto_ptr<FunctorCB<SndRcv, Item> >(new FunctorCB<SndRcv,
Item>(this, &SndRcv::output));

Here _cb holds a reference to an object and a member function to be
invoked on that object.  This allows me to make a function callback
into an object.  It allows me to save a closure that I can execute
later.

FunctorCB looks like this:
/**
 * @param T The type of the callback class
 * @param DATA The type of the argument passed to the callback
function
 */
template<class CB_OBJ, class DATA>
class FunctorCB : public ICallback<DATA>
{
public:
    typedef int (CB_OBJ::*PMF)(const DATA &data);
    FunctorCB(CB_OBJ *obj, PMF pf)	{ _obj = obj; _pf = pf; }
    int operator()(const DATA &data) { return (_obj->*_pf)(data); }

private:
    CB_OBJ *_obj;
    PMF _pf;
};

The above is extemely nasty, although it is efficient.
Dynamically typed languages just don't have that ugliness.
I mention this because both C# and Java are getting template support.