2010-04-21 4 views
3

Je suis en train de passer tant sur le terrain et la valeur d'un appel découverte:Est-il possible d'avoir des conditions de recherche variables pour la clé et la valeur?

@employee = Employee.find(:all, 
       :conditions => [ '? = ?', params[:key], params[:value].to_i) 

La sortie est

SELECT * FROM `employees` WHERE ('is_manager' = 1) 

qui ne retourne aucun résultat, mais lorsque je tente ce directement dans mysqsl en utilisant le même appel sans le '' is_manager, ça marche bien. Comment puis-je convertir mes params [: key] valeur à un symbole de sorte que l'appel SQL résultant ressemble:

SELECT * FROM `employees` WHERE (is_manager = 1) 

Merci, D

Répondre

1

Vous pouvez utiliser la substitution de variable pour le nom de colonne au lieu d'utiliser des valeurs de liaison:

# make sure the key passed is a valid column 
if Employee.columns_hash[params[:key]] 
    Employee.all :conditions => [ "#{params[:key]} = ?", params[:value]] 
end 

Vous pouvez sécuriser davantage la solution en assurant le nom de colonne passé appartient à un ensemble de pré sélectionné .:

if ["first_name", "last_name"].include? [params[:key]] 
    Employee.all :conditions => [ "#{params[:key]} = ?", params[:value]] 
end 
+0

Correction de l'erreur de syntaxe dans le code. –

+0

Je pense toujours que c'est une mauvaise idée du point de vue de la sécurité. – konung

+0

Ceci est une solution générique. L'utilisateur peut avoir un hash de clé valide et l'utiliser pour la validation (au lieu de columns_hash). Son problème d'origine est dû au fait que le nom col a été substitué en utilisant les variables bind et que les rails ont entouré les noms de col avec des guillemets. Ceci ne sera pas adressé en passant un symbole (au lieu d'une chaîne) pour le paramètre de nom de col. J'ai ajouté la validation 'columns_hash' comme ligne de guide pour ajouter une vérification pour limiter les noms de colonnes à un ensemble connu. Cela devrait être un problème de sécurité. –

3

Si vous souhaitez convertir une chaîne en symbole (qui est ce params [: clé] produit, tout ce que vous devez faire est

params[:key].to_s.to_sym 

2 points:

  1. Un mot d'avertissement: les symboles ne sont pas collectés.

  2. Assurez-vous que votre clé est pas un numéro , si vous convertissez to_s premier puis to_sym, votre code fonctionnera, mais vous pouvez obtenir un symbole bizarre comme ceci:

    :"5"

+0

Merci Nick. J'ai peur de poser la mauvaise question peut-être. @employee = Employee.find (: tous, : conditions => [ '=?', Params [: key] .to_s.to_sym, params [: valeur] .to_i) produit la sortie SQL suivante : SELECT * FROM 'employees' O WH ('---: is_manager \ n' = 1) Je pense que je dois avoir une erreur dans ma logique plutôt que de la syntaxe. Je pourrais faire une déclaration de cas où je vérifie ce que sont les params [: key] et fais la recherche appropriée (dans ce cas ce serait [: is_manager =?, Params [: value] .to_i]). Mais j'espérais être un peu plus dynamique et ne pas avoir à refaire chaque cas individuellement. – DarrenD

+0

J'ai répondu en quelque sorte ce que vous avez demandé, pas ce que vous vouliez dire :-) Je ne suis pas sûr que ce que vous demandez est possible ou le plus important - souhaité, du moins pas selon les rails spec http://api.rubyonrails.org/ classes/ActiveRecord/Base.html. Le problème est que c'est un gros trou de sécurité potentiel. Supposons qu'il s'agisse d'une application RH: que se passe-t-il si quelqu'un passe pour une clé = salaire. Ensuite, ils peuvent potentiellement tirer des informations sur le salaire ou des informations sur le SSN pour toute personne.Je veux dire que vous pourriez mettre toute sorte de sécurité basée sur les rôles, mais cela irait à l'encontre de l'objectif de vous faire gagner du temps que vous auriez passé à écrire votre déclaration de cas. – konung

+0

Gotcha. La clé provient d'une boîte de sélection, donc j'accepte seulement des valeurs spécifiques (plus je m'authentifie car c'est un outil 'admin'). Mais je t'entends. Déclaration de cas c'est :) – DarrenD

Questions connexes