Implémentation d'un ActiveRecord before_find
-
03-07-2019 - |
Question
Je construis une recherche avec les mots-clés mis en cache dans un tableau. Avant qu'un mot-clé saisi par l'utilisateur ne soit recherché dans le tableau, il est normalisé. Par exemple, certains signes de ponctuation tels que "-" sont supprimés et le boîtier est normalisé. Le mot clé normalisé est ensuite utilisé pour rechercher les résultats de la recherche.
Je gère actuellement la normalisation dans le contrôleur avec un before_filter. Je me demandais s'il y avait un moyen de faire cela dans le modèle à la place. Quelque chose de conceptuel comme un "before_find" callback fonctionnerait bien que cela n'aurait pas de sens pour un niveau d'instance.
La solution
Vous devriez utiliser des portées nommées:
class Whatever < ActiveRecord::Base
named_scope :search, lambda {|*keywords|
{:conditions => {:keyword => normalize_keywords(keywords)}}}
def self.normalize_keywords(keywords)
# Work your magic here
end
end
L’utilisation d’étendues nommées vous permettra d’enchaîner avec d’autres étendues. C’est vraiment le meilleur moyen d’utiliser Rails 3.
Autres conseils
Vous ne voulez probablement pas implémenter ceci en redéfinissant find. Remplacer quelque chose comme trouver sera probablement un casse-tête sur la ligne.
Vous pouvez créer une méthode de classe qui répond à vos besoins, par exemple:
class MyTable < ActiveRecord::Base
def self.find_using_dirty_keywords(*args)
#Cleanup input
#Call to actual find
end
end
Si vous voulez vraiment surcharger, vous pouvez le faire de la manière suivante:
À titre d'exemple:
class MyTable < ActiveRecord::Base
def self.find(*args)
#work your magic here
super(args,you,want,to,pass)
end
end
Pour plus d'informations sur les sous-classes, consultez ce lien: Astuces Ruby
comme dans ce qui précède, vous pouvez également utiliser une chaîne_method_alias
.
class YourModel < ActiveRecord::Base
class << self
def find_with_condition_cleansing(*args)
#modify your args
find_without_condition_cleansing(*args)
end
alias_method_chain :find, :condition_cleansing
end
end