06 December 2009

Add case insensitive finders by extending ActiveRecord::Base

I wanted to have an easy way of performing case insensitive searches using dynamic finders without manually constructing the query, so if I called a finder with the _ci suffix, e.g. Customer.find_by_name_ci('Big Kahuna Burgers'), it would result in a query with lower(name) = lower('Big Kahuna Burgers') in the where clause.

I could have created a new class that inherited from ActiveRecord::Base and overridden method_missing there, but then I and other developers would have to remember to derive all my models from this new class instead of ActiveRecord::Base. Instead I chose to extend ActiveRecord::Base itself.


Overriding in ActiveRecord::Base

This is the most obvious way of doing it - just reopen the class and add the functionality in. It's ok if you're adding something small but can get unwieldy as you add more.



In theory, it's also possible to put the new functionality into a separate module to make things a bit cleaner. You can do it using either extend or include. However, I couldn't make this work in production mode (but I'm including the code for the sake of completeness below).

Overriding using extend




The only trick is that you need to add your new method to ActiveRecord::Base as a class method, so you have to use extend instead of include:



Overriding using include


It's also possible to move alias_method_chain into your module, in which case you add just one line to ActiveRecord::Base:



To make this work, in your module you have to override self.included which gets called when the module is included. You also need to put your method in a sub-module, and call base.extend(ClassMethods). Also note the use of base.class_eval.



I put this code into activerecord_extensions.rb in the models folder, but it can go anywhere so long as it gets automatically loaded by Rails before you access your models.

Works on: Rails 2.3.5

0 comments:

Post a Comment