Breaking hearts
May 14, 2007 17:45 (Sydney Australia)
Apparently Giles was so broken hearted about my 7 seven line snippet he felt the need to write a 1700 word entertainment piece blog post. I don’t mind a good hearty discussion on the lack of computer-science in the web programming field, but let’s get the facts straight.
1. lower(email) runs a full table scan as opposed to using the index. That’s bad programming in any language.
That’s true, for some cases, but if you’re using PostgreSQL—which we are—you can quite easily add an index on the lower() expression.
I didn’t think it needed to be said, but when you see an abbreviated snippet of AR code it’s probably best not to assume too much about the DBMS’s execution plan without knowing a bit more info.
2. What happens when you call it with:
find_by_email("john@example.com", :conditions=>"true")
Nothing you wouldn’t have expected:
User.find_by_email('john@example.com', :conditions => 'true')
# User Load (0.000970) SELECT * FROM users WHERE (lower(email) = lower('john@example.com')) AND (true) LIMIT 1
3. with_scope is a Rails technique. A Ruby developer, someone who learned the language, not just the framework, would write:
find(:first, { :conditions=>"..." }.merge(options)
Shorter, simpler and a transferrable skill you can use outside of ActiveRecord.
Unfortunately Hash#merge won’t help you here. Observe:
{:conditions => "lower(email) = lower('john@example.com')"}.merge({:conditions => "true"})
# => { :conditions => "true" }
# whereas I wanted:
# { :conditions => "lower(email) = lower('john@example.com') AND true" }
with_scope gives you this desired behaviour.
For the record, I too agree that with_scope should be a protected method, and that using with_scope outside of AR is most probably naughty; but, using it internally, from within a well-tested ActiveRecord::Base subclass method, I think is just fine.
If you still feel that using with_scope internally is no better than sending polar bears to the slaughterhouse, do feel free to implement and publish your own version…
—tim: the idiot, self-saboteur, framework coder.

Comments
Lourens Naude
I use the above technique from time to time.Most likely as vulnerable to being massacred as the one in your post ( we tumble to share, don’t we? ), but it works, for me, on my project, today.
Change is good, constraints can be broken but a helluva lot of individuals in the community get off on mud slinging and quite frankly, Gile’s post is out of scope (pun intended).
Tim Lucas
Lourens: thanks for sharing, and welcome to “overriding finders anonymous” :)
Here’s another version too:Gabe da Silveira
I read Giles post and was not very impressed with gandiose statements like “the code is actually very troubled” and “*opts is a bug, lacking an understanding of how Ruby handles arguments.”
To call the use of
*optshere a bug belies the true intention of the author, which is to find any minor flaw and blow it out of proportion to make himself feel smart. Here’s a hint: good programmers get things done, they don’t obsess over the efficiency of every syntactic detail.This is to say nothing of the ad nauseam jaw flapping that characterizes rest of the post. If Giles had simply written a short paragraph about how inefficient the base query was, that would have been an interesting critique with some justification (albeit wrong in your case), but instead he conflates some perceived flaws in your code with some greater Rails competency crisis.
In one breath he is proclaiming some minimum standard of competence, then several paragraphs later he explains the process of transforming a database column into lowercase values. If he wanted to write something useful, he could propose an actual solution to case-insensitive search or merging multiple conditions “the right way” instead of pretending there’s no actual problem here other than the hideous offense of your ill-conceived code.
Tabloid journalism.
giles bowkett
Tim, everything you quote me as saying here was contributed by somebody else, and I identified it as such in the post. And most of the post had nothing to do with you at all. And I apologized for the criticism at the end of the post. And the part about Hash.merge() not working, I pointed that out myself in the original post!
That bit about the :conditions=>true criticism being flat-out wrong, you got me there, I should have tested it instead of listening to the person who said it, but other than that, all I can do is say that the criticisms came from someone else – which I said in the original post – that I’m sorry to criticize – which I said in the original post – and that I know about the Hash.merge() thing, and I can prove it, because I said it in the original post.
As for the “tabloid journalism” guy, dude, get a life. If it’s so bad, what did you read it for? What possible responsibility could I have for the fact that you won’t stop reading something after you decide you don’t like it? If you don’t like it, don’t read it! That’s easy!
Anyway, I’m really sorry I got everyone so riled up. I read your blog because I think you’re a good programmer. I can’t complain about the criticism because I started it, but enough already. I’m sorry. My bad.
Assaf
That’s what happens when good intentions and high emotions run together :-) Sorry about that.
1. You can make a lot of assumptions about lower() that are true in some cases and not in others. But Giles’ retracted post, to which I replied, didn’t state any of these. I think it was a bad idea for his to repost that.
2. Now that I’m looking at what you were trying to accomplish, my mistake. I stand correct. You’re actually doing the right thing.
3. There was a longer exchange going on
- thankfully not reposted, because at some point even I lost track trying to follow it -about the feasibility of extending where clauses in Rails. Suffice to say, I think the Rail’s limits are justifiable, but again it needs to have a context to make sense.The point of my post is a disagreement with the role Rails plays in all of these. Like Giles I’m cynical enough to see the impending migration of framework coders to Rails. Giles talks about “the Rails culture”, which sounds like trying to see Rails fail before it even gets a chance. I happen to think it’s a great framework for enabling developers to deliver better code (e.g. it exposes the SQL better than most other frameworks, makes the right choices about URLs, is HTML centric, etc), but it’s also just another framework when it comes to framework coders. And no framework can prevent you from making mistakes. Rails is neither the problem nor the solution.
At least, that’s my thesis.
Gabe da Silveira
Look, I’m sorry if I offended you, but that’s a copout. I’m not saying your writing is bad, it was an engaging read. I read through to the end to give you a fair chance to make a convincing argument. At the end it all seemed to boil down to a vicious attack on a piece of code that’s not all that bad to begin with. Your mistake was to hold this up as some sort of paragon of wrong-thinking. In doing so you open yourself up to a lot of criticism and you ought to be able to take it.
Daniel
Oh! Haha!
”... good programmers get things done, they don’t obsess over the efficiency of every syntactic detail.”
Was there something said about the “lack of computer-science in the web programming” somewhere? Sorry, no personal offense, I just couldn’t resist.
Alex Fetcher
Great site!
49753de578e6f638101fad07e28165a5
To comment on this article you must have javascript enabled.