10
votes

Rails Active Record Case insensible

Bien que dans I général comme sensibilité à la casse dans ma base de données, il y a quelques fois où je trouve une douleur. user_name et email sont de bons exemples de domaines dans lesquels je ne veux pas à vous soucier de l'affaire -. en particulier lors de la recherche

Il est assez facile de downcase une chaîne avant d'enregistrer en utilisant quelque chose comme:

before_save do self.email.downcase! fin

De cette façon user_name et des e-mails sont toujours enregistrés en minuscules. Mais quelle est la meilleure façon de find_by_user_name et find_by_email? Je me souviens de cours pour toujours downcase la chaîne que je passe dans ces méthodes - mais cela ne semble pas très sec.

Je pensais que sur le remplacement find_by_email et appelant l'original avec des super une fois que je l'e-en minuscule Amail, mais je n'a pas eu de chance comprendre cela.

Alors, quelle est la meilleure façon de le faire?

PS Je ne pense pas que les messages connexes comme celui-ci ( comment puis-je écrire un find_by_email insensible à la casse pour rails 3 ) tentent de résoudre le même problème. Personnalisé sql ici avec « inférieur » serait ointless pour moi depuis que je l'ai déjà assuré toutes ces valeurs sont plus faibles -. Il est celui qui vient en ce moment (probablement d'une forme où l'utilisateur est entré il) que je besoin en minuscule < / p>


4 Réponses :


19
votes

Un de ceux-ci devrait être bon: xxx

update :

Les fonctions Find_By _... Les fonctions sont en réalité non existantes. Lorsque vous appelez l'un d'entre eux, l'activerecord :: base attire votre appel dans la méthode méthod_missing et si le nom est bien formaté (contient des noms de colonne, etc.), la méthode de recherche appropriée est créée pour le classer. Après cela, il existera.

Si vous avez un wind_by_email , il sera appelé par défaut. S'il appelle Super , cela signifie que vous essayez d'appeler activerecord :: base.find_by_email , qui n'existe pas. Le manquant_method l'attrape et crée (réellement écrasé votre) recherche_by_email implémentation. C'est pourquoi pas bon d'appeler super là-bas. Si vous utilisez votre propre implémentation pour rechercher par courrier électronique, comme je l'ai écrit dans la deuxième partie, cela fonctionnera splendidement.


6 commentaires

Merci Matzi, j'aime vos suggestions et je vais mettre en œuvre le premier. Juste curieux recommanderiez-vous de créer cette nouvelle méthode plutôt que de remplacer la recherche_by_email? Pour moi, il semble que cela semble plus agréable puisqu'il est naturel de téléphoner à la recherche_by_email - mais je ne sais pas comment.


Dans Rails 2.0, il était imparfait, et lorsque vous avez appelé Super, la fonction manquée_method a remplacé votre fonction Find_By, ce qui ne fonctionne qu'une seule fois. Je ne sais pas si cela est corrigé, mais mieux d'être sûr que par désolé. Si vous souhaitez appeler Find_By_Email, utilisez ma deuxième option, cela devrait fonctionner de toute façon.


Désolé, ne suivez pas la dernière partie que vous avez écrite "Si vous souhaitez appeler la Find_By_Email, utilisez ma deuxième option ...". Dans votre deuxième option, n'appelle-je toujours pas de la recherche_by_lower_email?


Je veux dire que les deux parties de ma fonction sont deux implémentations différentes. Le second peut être utilisé si vous appelez la fonction Find_By_Email.


impressionnant. Merci pour la révision. je comprends. Je vais mettre en œuvre la deuxième solution.


Rappelez-vous simplement pour la deuxième méthode offerte: Find_By_Email renvoie un résultat normalement, vous devrez donc appeler .First sur la réponse de la matrice de méthodes écrasée si vous le souhaitez normalement.



12
votes

J'ai fait quelque chose comme ceci:

Member.where("lower(email) =?", email.downcase).first


3 commentaires

Soit je manque votre point ou vous avez manqué le point de ma question. Je conviens que, généralement, vous devriez downcase avant d'économiser. Si vous supposez que cela est fait, vous n'avez pas besoin du "Basse (email) =?" Partie mais vous auriez toujours besoin de la pièce email.downeCase - étant donné que l'adresse e-mail est fournie par l'utilisateur et qu'elles ne sont peut-être pas basses - c'était le point de ma question. Je crois que la réponse de Matzi est correcte.


Eh bien, vous devriez savoir si c'est ou n'est pas alinéa sur l'insertion dans la DB. Il semble que la réponse de Matzi est une excellente solution, mais ses hypothèses de fabrication que l'e-mail est inférieur à la DB ou est moindre à la masse lorsqu'il est passé dans la méthode Find_By_Email, je crois. Son retournera également un éventail de courriels, tandis que: Premier retourne la première réponse en tant qu'objet membre actuel. Non?


Vous faites un bon point sur: Tout d'abord. Je ne pense pas qu'il est faux de supposer que l'e-mail est décalé dans la solution car cela est spécifiquement noté dans la question.



34
votes

avec PostgreSQL Vous pouvez faire:

User.where("email ILIKE ?", email).first


5 commentaires

Est-ce vulnérable à l'injection SQL?


Pour être clair (pour les futurs lecteurs), la version de la question est sûre de l'injection SQL. La version dans le commentaire n'est pas.


@Kevin la version de quoi, rails? PostgreSQL?


@évanrmurphy On dirait qu'il y avait un ancien commentaire qui a depuis été supprimé que je faisais référence à.


user.find_by 'email ilike?', email est comment RubroCOCOP recommande ceci, en utilisant recherche_by au lieu de.



0
votes

Cela fonctionne pour moi! merci, mais avec inférieur (: xxx).

Client.Inclut (: Responsables). Où (["Basse (nom (nom) || inférieur (contact) || cnpj || clients.rg || rg ilike?", "% # {param '[: recherche]} % "])


0 commentaires