How would you implement this normalizer?


#1

Names of models in my application have accented characters that imply
unexpected orderings. For instance Ávila should go before Madrid, but
String#<=> puts it the other way aroud.

I am only sorting for views, so it would be OK to do some
normalization on-the-fly on Ruby land, and since the same criteria
has to be used throughout the application I was thinking on some sort
of generator whose usage would be:

class User < ActiveRecord::Base
normalize_for_sorting :surname
end

The intention is not to modify surname, we need it in the views,
normalize_for_sroting would generate a method
User#surname_for_sorting and configure it as a creation/finding
filter that applies the necessary tr///. The aim is:

  • We normalize the strings once and store them in
    attributes instead of applying the normalizer
    in all sort blocks

  • The tr///, the configuration of filters, etc. is
    written in one place, following DRY.

I think that can be done, but I am not fluent enough yet in Rails to
determine whether it is a clean solution, and how to implement it in
an idiomatic way. Any advices?

– fxn


#2

How about modifying your data before putting it in the database?? That’s
how i do the “trick”.

===
class User < ActiveRecord::Base

def before_save
self.surname_for_sorting = normalize_for_sorting :surname
end
end

or… if you don’t want extra data in the db, and format it for every
request.

===
class User < ActiveRecord::Base

def surname_for_sorting
@sfs = normalize_for_sorting(:surname) if !@sfs
@sfs
end
end

If you desperately want more DRY, make it a mixin.


#3

On Feb 19, 2006, at 22:53, Colin wrote:

end

If you desperately want more DRY, make it a mixin.

What I have in mind is: a class method for models that generates
for_sorting accessors on-the-fly based on parameters, and that
creates callbacks after
(save|find) that initialize those attributes.

I guess class_eval is all what I need, but which is the idiomatic way
to define normalize_for_sorting so that is visible in all models? Do
I open ActiveRecord::Base and add the method? If that’s the way,
where do I do that? In which file?

– fxn