It all started from this comment in Devise’s issue tracker. As you can see “logging in” feature didn’t work for the user (well it’s a main feature of the Devise gem and this should work for sure). And I decided to take a deep look at this issue.
So as you can see from the backtrace the error was about
ArgumentError was added to the Rails 4.0 and it raises when you’re trying to call
order method with blank arguments. Honestly, I don’t see any reason for adding such “feature” to Rails (you can find an explanation of this behaviour here). Anyway let’s go further.
If you didn’t know Devise uses orm_adapter gem to access different databases with different ORMs. If you look at the backtrace you’ll see this line of code. So we’re calling
order with some params. After some time spent on debugging I figured that
order_clause(order) returns blank string (
"") in our Devise-specific case. But the thing is that
order method accepts a blank string since
order method uses splat operator and our blank string becomes an array with a blank string (
[""]) which returns false for
blank?. So why the hell it doesn’t work?
And then I looked at the
lib app and I saw this (you can find that app here):
1 2 3 4 5
Yeah, that’s it. Just a simple Ruby core extension to the String class. What bad can happen?
But let’s look closer to the RubySpec of splat operator:
What does it mean? Let’s try splat operator in IRB:
and with that extension:
See the difference? With this extension it becomes a blank array
 which returns true for
Why? According to the RubySpec
Since we have method
to_a defined on String object it’s predicted behaviour for the Ruby but not for our app and Rails in particular. And ActiveRecord fails because it knows nothing about this.
So please, be careful with extensions to the Ruby core classes!