2010-07-03 5 views
9

Je travaille sur une application de rubis sur rails. Pour un contrôleur de session, je souhaite utiliser un cas pour vérifier si le compte d'un utilisateur est verrouillé ou interdit. J'essaie d'utiliser l'objet d'une classe comme cas, et d'utiliser quand vérifier les attributs.Boîtier/Interrupteur Ruby on Rails. Comment faire correspondre à l'objet?

Par exemple,

user = Profile.find(1) 
case user 
when user.ban 
    redirect_to() 
when user.lock 
    redirect_to() 
else 
    redirect_to() 
end 

Le seul problème est que cela ne fonctionne pas.

Qu'est-ce que le travail est la suivante:

case user.ban 
when true 
    redirect_to() 
else 
    redirect_to() 
end 

Tous les conseils sur la façon dont je peux vérifier si un au sujet de l'objet utilisateur est interdit ou verrouillé à l'aide d'un interrupteur?

Merci

Répondre

19

faire une méthode de user.status qui retourne un état d'un utilisateur, vous pouvez le faire:

user = Profile.find(1) 
case user.status 
when "banned" 
    redirect_to() 
when "locked" 
    redirect_to() 
else 
    redirect_to() 
end 
+0

Merci pour toutes les réponses. J'ai trouvé la réponse de Zepplock la plus utile pour mon application. La seule différence est que j'ai utilisé des symboles dans la méthode et le cas. Voici la méthode que j'ai écrit: état def si self.ban retour: interdiction fin si self.lock retour: verrouiller fin fin – Brian

+0

@ Brian: Juste pour Rubify un peu - si une fonction retourne un booléen, c'est une bonne forme de le nommer avec un point d'interrogation. De même, même si les post-modificateurs peuvent être abusés et nuire à la lisibilité, dans ce cas je pense qu'ils travaillent pour l'améliorer: 'statut de défection; retour: interdit si interdit ?; retour: verrouillé si verrouillé? end' – Amadan

0

vous pouvez faire comme dit Zepplock. Mais pour un exemple donné, suivre la meilleure voie (juste un exemple)

action_name = (user.ban)? "ban" : ((user.lock)? "lock" : "default") 
redirect_to(:action => action_name) 
13

J'aime la réponse de @ Salil; Cependant, si vous aimez vraiment case, vous pouvez le faire:

case true 
    when user.ban 
    redirect_to() 
    when user.lock 
    redirect_to() 
    else 
    redirect_to() 
end 

MISE À JOUR Jörg dit que cela fonctionne aussi, et il a raison! Donnez-lui quelques votes sur sa réponse! (Comme on I)

case 
    when user.ban 
    redirect_to() 
    when user.lock 
    redirect_to() 
    else 
    redirect_to() 
end 

MISE À JOUR 2012 Cela fonctionne maintenant:

case user 
    when lambda(&:ban) 
    redirect_to() 
    when lambda(&:lock) 
    redirect_to() 
    else 
    redirect_to() 
    end 
end 
+0

+1 pour ne jamais penser à utiliser vrai comme condition de cas. – Salil

+0

Je suppose que l'ordre des when s est sacrément important, n'est-ce pas? Quoi qu'il en soit, +1 pour une idée tellement incroyable. –

+3

Ceci est inutilement compliqué. La raison pour laquelle cela fonctionne est que 'true === true' est vrai. Mais l'autre forme de l'expression 'case', c'est-à-dire simplement omettre le' true' tout à fait, fait déjà la même chose de toute façon. –

0

@ Brian, l'idée d'un boîtier de commutation est que vous avez une variable qui accepte une valeur dynamique et le vérifie contre un couple d'ensemble constant de valeurs. Dans le morceau de code que vous avez écrit, les instructions case contiennent des valeurs dynamiques comme user.ban qui dépend de la variable elle-même que vous essayez de vérifier. La façon correcte d'utiliser un boîtier de commutateur est la façon dont @Zepplock a démontré.

2

Lol, j'adore la réponse d'Amadan. Et si vous voulez vraiment une déclaration de cas, vous devriez probablement faire ce que Zepplock a dit (bien que vous puissiez considérer les symboles à la place des chaînes), mais en fonction de votre cas d'utilisation, vous voulez une solution plus basée sur les instructions.

De toute façon, j'ai pensé que je jetterais et amusez-vous aussi^_^ Voici une solution qui fonctionnera avec ce que vous avez dit, il crée des objets qui répondent à === (ce que les déclarations de cas utilisent), puis ils invoquent la méthode d'intérêt (verrouiller ou interdire) et la renvoyer. Vous devriez probablement les mettre dans une sorte de config ou initialiseur ou autrement stocker les résultats après le premier appel, afin de sauver des performances (votre application n'a besoin que de créer ces objets une fois)

user = Class.new do 
    def ban() true end 
    def lock() true end 
end.new 

def banned? 
    ban_checker = Object.new 
    def ban_checker.===(user) user.ban end 
    ban_checker 
end 

def locked? 
    lock_checker = Object.new 
    def lock_checker.===(user) user.lock end 
    lock_checker 
end 

case user 
when banned? 
    puts 'banned' 
when locked? 
    puts 'locked' 
else 
    puts 'default' 
end 

Note: I Je ne préconise pas cette solution, car elle viole l'encapsulation. Banned doit être défini et utilisé sur votre utilisateur, mais pour que cela fonctionne, il doit être défini dans la portée englobante.J'apporte la plupart du temps cela pour le plaisir :)

7

Juste le laisser user:

user = Profile.find(1) 
case 
when user.ban 
    redirect_to 
when user.lock 
    redirect_to 
else 
    redirect_to 
end 

Dans Ruby, il existe deux formes de l'expression case. Dans le formulaire ci-dessus, il exécute simplement la première branche qui évalue à une valeur vraie (c'est-à-dire n'importe quoi sauf nil ou false).

L'autre forme

case foo 
when bar 
    baz 
end 

est équivalent à

if bar === foo 
    baz 
end