On 25 December 2012, Ruby version 1.9.3-p362 was released. Is that dedication, or what?
Yesterday, I decided to upgrade to this new version of Ruby that contains only bug fixes.
Sure, the site loads… But if you try to create a new record via the front-end UI, it craps out with an Internal Server Error.
Digging a bit deeper, it seems this new Ruby version causes a “stack level too deep” error in /active_record/transactions.rb – at least when using Rails 2.3.x.
So, how do we fix this little problem?
If you’re like me, you still have some Rails 2.3.x apps hanging around. Yeah, Rails 3 is awesome in some respects, but that “2x performance increase” never quite materialized.
In fact, for the most part, Rails 3 is still slower than Rails 2.3. SIGH!
Nevertheless, Ruby itself is progressing nicely. Ruby 1.9.3-p0 was released a few months ago. With faster garbage collection, startup, and file load times, Ruby 1.9.3 is where it’s at.
The only question is: What do you do to make Rails 2.3 play nicely with Ruby 1.9.3?
It’s actually not that hard!
Let’s say you were using Rails 2.3.x, and you made the (wise) decision to implement heavy fragment caching. Then let’s say that you updated to Rails 3.x. At that point, you probably noticed that Rails 3 does something seriously annoying with the paths where it caches fragments.
In Rails 2, doing this:
<% cache('posts/123/123456/main') do %>
Gave you a cache file that looks like this:
However, in Rails 3, the same cache code results in a cache file that looks like this:
WTH? That’s not documented in the Rails 3 API. So what’s going on, and how do you make Rails 3’s fragment caching work like it used to instead of using those crazy hash subdirectories? Read on!
If you’re like me, you’ve got a Rails 2.3.x application running on Ruby 1.8.x – or perhaps Ruby Enterprise Edition. Well, that’s all fine and dandy, but Ruby 1.9.2 is about twice as fast as even REE 1.8.7. So, you’ll probably want to upgrade to the new version of Ruby.
Problem is, you upgrade Ruby and then your Rails 2.3 app starts whining about character encoding problems. Heck, it might not even run! So you search the net in vain trying to find a simple, step-by-step explanation of what you need to do to make your app run with the speedy 1.9.x version of Ruby. And, you pretty much come up empty handed.
Here I shall endeavor to outline all the steps necessary to install and convert your Rails 2.3.x app to work flawlessly with Ruby 1.9.x.
Every web programmer knows that UTF-8 is where it’s at these days. Even if you are coding something for only the US market, you’re still probably going to run into names, addresses, or whatever with accented characters.
Everyone knows that “all you have to do” is make your app speak UTF-8, set the character encoding in your web pages to UTF-8, and set your database encoding and collation to something like
utf8_unicode_ci, and you’re off and running… right?
Not quite. You’ve probably run into the situation where you hop into phpMyAdmin and edit some table row, and what to your wondering eyes should appear, but something like this:
Voici un article franÃ§ais.
Well, crap. That’s supposed to be a “ç” in “français”, not an “Ã§”!
And yet, when you view the web page and edit the content in your app, it looks and works fine! What’s going on here?
It’s really quite simple, and apparently something that no one bothers to mention: you have to tell your app to communicate with the database in UTF-8! Here’s how you do that in PHP and Rails…
If you have a Rails app that sends e-mails, you are probably using ActionMailer. Unfortunately, starting with Rails 2.2.2, you may have encountered a wonderfully annoying little error that looks like this:
OpenSSL::SSL::SSLError (hostname was not match with the server certificate):
The are quite a few sites out there that give monkey patches for this problem, but those aren’t very useful because the next time you upgrade Rails, the monkey patch gets obliterated and you’re back to square 1. And then you have to remember how you monkeyed with it the last time to get it working again. Ug…
Instead, fix it the right way!
If you use Rails on a high-traffic site, you know that as your number of users increases, you have three main options:
- Add servers to handle the load
- Optimize your queries
- Improve your caching scheme
You may be surprised to know that most people go for Door #1. It’s a lot easier. You don’t have to really do tons of work to rewrite your code and actually make it efficient. You don’t have to ditch “the Rails Way” and start actually thinking about what the database layer is doing to slow your site down to a crawl. And you don’t have to think about how Rails’ cache expiry functions actually work. Finally – and best of all – you can just pass the costs on to your customer, right??
I recently read an article that really slayed me. It was about a “niche site” that runs on Rails. They get 50 million hits a month, and they have SIX servers to handle the load, including multiple dedicated DB servers. I designed a Rails site that now gets 27 million hits a month, and it runs Rails on a single 1.86 GHz dual-core server with 3GB of RAM. By my calculations, the site could easily handle twice as many hits as it does now. Most of the time, the load is very low and the CPU and disk accesses hover at a few percent.
Of course, to achieve good performance, you can use things like Phusion Passenger. But that alone ain’t gonna cut it. You also have to optimize your queries, stop doing things The Rails Way and start thinking for yourself, and of course optimize your caching scheme.
In this episode, I’m going to tell you one very cool way to turbocharge your caching setup!
Say you were using the active_record_store for sessions in Rails 2.2, and you added your own custom column(s) to the default sessions table in your database. You might have done so because you wanted to add, say, the user’s id number to each entry in the sessions table. This would let you do things like quickly and efficiently delete a user’s session.
Unfortunately, when you upgrade to Rails 2.3.2, your session hack will be seriously busted. Cookies will work great, and so will the standard session scheme, but your custom column in the sessions table won’t be updated. Worse yet, you’ll get a lovely error when you do things the old way. The problem is due to 2.3.2’s new “lazy sessions“. In short, unless a session is accessed, it doesn’t load all the session handling stuff. If you don’t want to use sessions, you don’t have to turn them off anymore.
So, that’s great, but your custom sessions table is still broken. There are no solutions posted anywhere that I could find, so I took the liberty of figuring it out myself. Here’s what to do…
Ruby on Rails has become a rather popular framework that many have used to easily and quickly create some pretty powerful web sites. As with any web programming language or framework, it certainly does have its problems. For example, Rails has never been well-known for its incredibly speedy database layer. In fact, if you’re not careful, you can make a glorious application that will run your server into the ground because of all the heavy behind-the-scenes DB queries.
Another problem is that a lot of people get their Rails coding tips and tricks from others – basically what you’re doing right now! The solutions you find online aren’t always optimal, and are sometimes downright scary.
Take a custom 404 error page. It’s easy enough to make, but you have to be careful about how you actually implement it.