You Got Yer Merb in my Rails
December 23rd, 2008
So, the Rails blogosphere is all abuzz with the news that Merb will be merged into Rails for the 3.0 release.
Now, I haven’t done much more that a few minutes of messing with Merb here and there… and that was quite a while ago. However, Merb’s philosophy struck me as much more “no set way to do it” rather than “convention over configuration”. Seems like that would make for a potential culture clash.
It sounds like the parties involved are determined to work it out though. And really, I think that would be a good thing for the Rails world, to become a little less insistent about the conventions. Ok, maybe “insistent” isn’t the right word. But Merb has definitely pushed the reconfigurability angle.
But all that philosophy shit aside, there is one burning question this raises for me: what will happen with “render”?
This may seem silly but one of the things that most excited me about Merb was that it just renders the last thing you tell it to render… no more DoubleRenderErrors. It would be awesome if Rails switched to that approach. Uh, though there’ll be a lot of gutting of if/else blocks to do. ![]()
Rails Gotcha
August 29th, 2008
This is another sort of “reminder” post, mostly for myself, but maybe it’ll save someone else’s butt.
Rails offers lots and lots of nifty, terse bits of helpful code… like validations and named scopes. The gotcha is that you have to be careful to distinguish between code that gets read — and cached — at class load-time and code that will be evaluated at runtime.
To be more specific, yesterday at work, we were having problems with newly-deployed code not behaving as it had on the test server. We had added a “silencing” feature to prevent trouble makers from posting or chatting on our site. The silencings expire after a while, but we were seeing them fail to expire once we deployed to production.
Well, I tracked the problem down to this named scope to find the active silencings:
named_scope :active, :conditions => ['scheduled_end > ?', Time.now]
The problem, of course, is that the named_scope is evaluated when the class is loaded, which means that the time used in the query will be the time the class was loaded… and stay that way until the class is reloaded again.
The solution is to give named_scope a lambda:
named_scope :active, lambda {
{ :conditions => ['scheduled_end > ?', Time.now] }
}
That way the lambda is evaluated at runtime and Time.now does the right thing.
I remember back when I was starting out with Ruby that lambda was one of the concepts that it was hard for me to internalize. But this example makes it really clear: it’s just a chunk of logic passed around like data. And when the time comes its executed.
Now, this is all really pretty basic stuff; if you’ve used named scopes a lot, you probably already know all this. However, this bug slipped past us until it was actually on production. Why? Because we test on testing servers, to which all the devs are constantly deploying. So, the server gets restarted frequently, causing the time in the scope to get updated and the old silencings get expired. The code looks fine and appears to run fine. It’s an easy bug to creep in.
Actually, I found it fairly quickly because I just got burnt by a similar thing last week. I had a validation that built a regex using an array of terms loaded from the db. We had an admin page for adding terms, but the regex in the validation wouldn’t change until the class was reloaded. And then as well, the test server was being reloaded often, so the bug slipped by for a while. (Note that you can’t pass lambdas to the validation macros… had to define a method and give the macro the name of the method.)
This seems like it would be a good thing to put in a Lint for Rails. It’s strange that there still isn’t such a beast… that I’ve been able to find anyway.
Note to Self
August 5th, 2008
I don’t know why I always forget this little gotcha. This time it occurred to me, “hey, you have a blog now… stick it in your blog and then maybe you’ll find the answer faster next time”.
So here’s the deal: when you’re trying to use a Rails URL helper and you get the a NoMethodError for “nil.to_sym”, that means you’re using a plural where you should be using a singular… dummy.
Actually, I’ve always been annoyed with the pluralization crap in Rails. Computer programming was going along fine doing everything with singular nouns. But no, Rails had to make me remember yet more stuff. I think one of these days I’ll have to write a patch to Rails just to allow me to do MyModels.find :all… note the “s” there. I don’t know why my brain insists on doing this, but I do it over and over.
Oh well, I guess I shouldn’t blame Rails for my brain damage. Anyway, the above cryptic error is now recorded for posterity. Maybe it’ll help someone else out there too.
OSCON Craziness
July 27th, 2008
So, this past week in Portland saw the O’Reilly Open Source Convention come to town. I didn’t go to the convention — didn’t even set foot in the Convention Center the whole week — but I did partake of some evening activities.
On Tuesday, the PDXFUNC (Functional Programming group) met for dinner at Old Town Pizza. I’ve been on the pdxfunc list since it started, but have never made a meeting, so I thought it would be nice to finally meet some people from the group. Turned out that not too many people made it — and some were conference attendees from out of town — but we had a nice little conversation anyway. It also turned out that the Free Software Foundation was having a party upstairs at OTP, so I crashed that after a while and had some nice chit chat about various open source issues.
Wednesday night was FOSCON (Free OSCON), an annual meeting on one night of OSCON put on by the Portland Ruby Brigade. This featured — besides free beer and pizza — about a dozen lightning talks and then a coding competition. Most of the lightning talks were interesting… kind of super quick “hey, check this out” talks.
The coding competion pitted four teams using different web frameworks to build a simple cookbook website in 20 minutes. The teams were: Rails, PHP Symfony (actually one guy), Drupal, and Seaside. I volunteered to be a judge. The results were fairly predictable. The assignment was pretty Rails-friendly (the classic, early rails tutorial by Curt Hibbs was a cookbook site)… must have pretty urls, must have validations with error messages, must have this model and this controller, etc.
The Rails team pretty much fulfilled all the requirements in the allotted time. The Symfony team missed a requirement or two, but we cut him some slack because he was on his own.
The Drupal guys just downloaded a bunch of tarballs and then set the whole thing up in the browser. They were actually “done” in about eight minutes. But it turned out that they had overlooked quite a few requirements and so, threw away what would have been a crushing victory. There’s no doubt that if you need a simple, database-backed website, you can throw it together ridiculously quickly with Drupal. If your requirements get too far into the realm of custom logic and what have you, then you’d be doing code customization… and I’d rather not do that in PHP, thank you.
The Seaside team spent the whole twenty minutes typing in the Smalltalk “code browser”, but did not have much to show at the end. They just didn’t have any generators or scripting help, and had plenty to type. However, Seaside still gets some points for coolness factor: it’s image based, so there is no database needed… you only deal with Objects. It is also continuation-based, so a site is just a tree of objects that know how to write themselves as HTML on an HTTP canvas and the current state of that tree is just remembered between requests. It’ll be interesting to see if anyone does this sort of thing for Ruby once Gemstone’s Maglev Ruby VM is released.
Anyway, the results of the competition wound up being first to last place in the order I’ve mentioned them here. However, had the Drupal team paid closer attention to the requirements, they would have shredded. Also, had the Symfony representative had a pairing partner, it may well have been a tie between the two. All-in-all that was a great evening. It would have been interesting to have Python (maybe Django) and Java (maybe Stripes) represented… though we ran about an hour over time as it was.
The following night, I crashed the Beerforge party at Bossanova, which was put on by Open Source Labs. That was pretty sweet… free food and booze for a couple hours. The name was a little ironic, since the beer selection was pretty lame… though it turned out to be safer than the consistently crappy cocktails. I had several nice conversations there, including chats with people from RightScale — a Rails-based deployment solution — and Jive Software, which is the local Java shop responsible for Openfire… the open source XMPP server which Kongregate uses for it’s in-game chat.
What a week… and I still got work done during the day!
My First Rails Patch
June 11th, 2008
Well, I submitted my first Rails patch proposal to Lighthouse today.
At work we have some awfully large database tables, so it’s important that queries hit an index. Apparently MySQL has to be persuaded to use an index sometimes. So, we use the ActiveRecord :from option — which allows you to specify the table name as a string — and include USE INDEX(my_index_name) in there:
HighScores.find(:all, :from => 'high_scores USE INDEX(index_type_statistic_date_value)', :conditions... )
However, when we tried to use the same :from option that we used on a find query on a count query, we discovered that the Calculations module (which provides the AR::count method, amongst others) did not accept the :from option.
So, I checked out a fresh copy of rails from github, made my own branch, made my changes and made a patch file. Then I submitted that to the Rails Lighthouse project. You can add your comments (preferably plus ones) at:
Now, I’ll just have wait and see if this gets accepted. It’s a pretty minor change, is matching existing functionality in Base, and I included tests, so hopefully it’ll be a no-brainer.
By the way, I used the most recent railscast, “113 - Contributing to Rails with Git“, to figure out all the stuff I needed to do to with Git and Lighthouse and whatnot. It was very helpful and I highly recommend it if you’re interested in contributing to Rails. In fact, they should just put a link to it in the Rails Lighthouse project.
So, let’s see… I learned a bit about using Git, some more about the inner workings of ActiveRecord, set up my account on Lighthouse, etc. A good learning experience to be sure.
– epilogue:
Posted that patch to Lighthouse and pasted the url in #rails-contrib and it was accepted and applied in about 10 minutes! I have to say that my first experience contributing to Rails was a very good one. I never dreamed it would be so fast and easy. ![]()
Ruby Timeout Magic
June 7th, 2008
I recently used Ruby’s Timeout module to help deal with a potentially slow call to Facebook. This is a neat little bit of code. It simply spawns a thread that sleeps for the number of seconds passed to the timeout method call. If the original thread is still alive, it raises an exception… in the original thread.
This has an interesting side-effect. I was initially a bit annoyed that timeout raises an exception because the code I am wrapping in the timeout is already in a rescue block. I was thinking I would need to wrap my call to timeout in another rescue block… like this:
begin
timeout(30) {
begin
# make facebook API call
rescue Exception => e
logger.error("Calling facebook raised: #{e.message}"
end
}
rescue Exception => e
logger.error("Calling facebook timed out")
end
However, I’m lazy. I was initially just catching Exception, as above. Before I got around to putting in the outer rescue block, I discovered that my tests were passing even when I forced the timeout to trigger.
This is because timeout raises it’s exception in Thread.current. That’s right, when the timeout thread sees that the original thread is taking too long, it reaches into the other thread and makes it throw. Consequently, the inner rescue catches the timeout exception raised by a time out block wrapping it.
This means that I can just do this:
timeout(30) {
begin
# make facebook API call
rescue Exception => e
logger.error("Calling facebook raised: #{e.message}"
end
}
I suppose this isn’t really that magical… just a side-effect of multithreaded programming. However, I think the common expectation (at least from your typical sequential programmer’s point of view) would be that the inner rescue block could only possibly catch exceptions raised within the previous begin and itself. Not so.
Advanced Rails Review
June 7th, 2008
Here’s a review I wrote a while back (Feb. 2008) of Brad Ediger’s Advanced Rails. I have review copies of The Rails Way by Obie Fernandez and The Ruby Programming Language by Matz and David Flannagan, but haven’t made much of a dent in them. I will try to post at least a quick review of both soon.