> but there's a culture of not trying to be too clever
I love Ruby dearly, but I can't agree with this. There's a lot of being "too clever" in Ruby land. Not in terms of writing fiendishly convoluted but brilliant code (though we do have a nice subset of "code as art", like _Why's Camping micro-framework), but in terms of caring too much about elegance over things like speed and memory usage, until it comes back to bite us.
My pet peeve at the moment is Bundler and Rubygems, which while they are fantastic productivity tools when you start out, has the serious issue that the way they grow the load path means that the time to require a file grows exponentially with the number of gems. 100k+ failed stat calls on startup just to try to be "too clever" about not making people specify more clearly exactly what they are loading is no fun.
Many of these "too clever" things then starts to dictate app design. E.g. if you want to make a command line app out of a large tool that depends on a long list of gems and Bundler, you better think long and hard about making sure you defer all loading as much as you possibly can, or alternatively start up the app in the background and make a small command line app that talks to it over a socket...
For my part, I have a longer list of other Ruby practices I've come to detest than most, probably, as I'm working on a "as static and ahead of time as possible" Ruby compiler, and there's a lot of Ruby idioms that massively complicates things because Ruby developers are used to the malleability of the language, and so will often alter fairly central parts of the language even when there may be conceptually simpler ways of achieving the same that just doesn't look quite as clean.
Again Rubygems is a great example: It replaces "require". That's one of the means it uses to munge load paths. On the surface it was a great thing: it let Rubygems let people pretend Rubygems wasn't there, and yank out gems in favour of manually installing the files if they wanted to. But it came at the cost of contributing to the load path/stat mess I mentioned above.
Some of these things are in fact great no matter what, and exactly why we love our languages. But some of them come with ugly warts that we grow blind to because we understand the underlying reasons for why things have been done the way they have.
I think all languages grow these kind of warts. To me, Java has more of them than most... Java from beginning seems to have grown a culture of ceremony and abstraction that due to the language easily (but not necessarily) ends up with very verbose code.