def ~; end

Pratik lately is doing a great work refactoring ActiveRecord to make a full use of relations. Speaking in code language, this means that in Rails 3 you will be able to do:

  User.where(:name => "Jose").order("birthday")

And it will return a relation. The relation can be further manipulated and the query is only triggered when you call all, first, to_a or some Enumerator method.

Besides that, he’s also doing some crazy experiments, which will probably become a plugin later. While discussing with Pratik some ways to implement equality and inequality, I discovered a neat ruby trick. Open up an irb session and do:

MD7M9TSHSAJY
~2  #=> -3
~42 #=> -43

And this method is actually documented.

The nice thing though, is that you can define this method in other classes as well. In the querying scenario for example, we could add this behavior:

class Symbol
  def ~
    :"LOWER(#{self})"
  end
end

And now we could actually do:

User.where(~:email => "jose@plataformatec.com.br")
#=> SELECT * WHERE LOWER(email) = "jose@plataformatec.com.br"

Unary operators

Yehuda Katz later pointed to me that this can actually be done with any of the three unary operators in Ruby: +, – and ~.

So we could also do:

class String
  def +@
    upcase
  end

  def -@
    downcase
  end
end

And now:

+"jose" #=> "JOSE"
-"JOSE" #=> "jose"

You could even “go crazy” and append several unary operators:

+-+"jose" #=> "JOSE"

And you? Did you know such behavior in Ruby? Do you have any good use case for it?

10 responses to “def ~; end”

  1. Samuel Flores says:

    I’m writing a parser with Treetop and used this feature to simplify the usage in irb. When I write -“sample” my lib load a file called “sample” in the current directory, execute the parser on its content and return the generated tree.
    It’s a cool feature 😉

  2. Samuel Flores says:

    I’m writing a parser with Treetop and used this feature to simplify the usage in irb. When I write -“sample” my lib load a file called “sample” in the current directory, execute the parser on its content and return the generated tree.
    It’s a cool feature 😉

  3. TaQ says:

    Things go even more funny with the Ruby 1.9 file encoding support and “crazy methods”! For example, a not so nice to type method like ∑ could be used like User.∑, returning the users count or User.∑(:credits) returning the sum of the users credits on the system or something like that. Ok, ∑ is not really a cool example, but … 😉
    More about it here http://tinyurl.com/5j8ofe and http://tinyurl.com/5l9xgd

  4. TaQ says:

    Things go even more funny with the Ruby 1.9 file encoding support and “crazy methods”! For example, a not so nice to type method like ∑ could be used like User.∑, returning the users count or User.∑(:credits) returning the sum of the users credits on the system or something like that. Ok, ∑ is not really a cool example, but … 😉
    More about it here http://tinyurl.com/5j8ofe and http://tinyurl.com/5l9xgd

  5. Jack Dempsey says:

    Reminds me of things you can do with Sequel. Might be a good source of inspiration.

    http://sequel.rubyforge.org/

  6. Jack Dempsey says:

    Reminds me of things you can do with Sequel. Might be a good source of inspiration.

    http://sequel.rubyforge.org/

  7. This is a neat trick, but not something I believe people should use in practice; I think it makes code unreadable.

    If I see +some_string in a codebase, I have to go digging through files to find where it’s monkey-patched and what the method does.

    If I run into all_caps(some_string), at least I have a hint as to what it’s doing.

    And even better, some_string.upcase is in the standard library and I already know what it does.

    And good luck grepping for method names like “+”, “-” and “~” in your source code. :/

    So yeah, I’d file this away as fun but impractical.

  8. This is a neat trick, but not something I believe people should use in practice; I think it makes code unreadable.

    If I see +some_string in a codebase, I have to go digging through files to find where it’s monkey-patched and what the method does.

    If I run into all_caps(some_string), at least I have a hint as to what it’s doing.

    And even better, some_string.upcase is in the standard library and I already know what it does.

    And good luck grepping for method names like “+”, “-” and “~” in your source code. :/

    So yeah, I’d file this away as fun but impractical.

  9. Reminds of crazy Haskell syntax, although this is much saner 🙂

    http://briancarper.net/blog/real-confusing-haskell

  10. Reminds of crazy Haskell syntax, although this is much saner 🙂

    http://briancarper.net/blog/real-confusing-haskell