2010-07-03 9 views
9

Pracuję nad aplikacją ruby ​​na szynach. W przypadku kontrolera sesji chcę użyć skrzynki do sprawdzenia, czy konto użytkownika jest zablokowane lub zbanowane. Próbuję użyć obiektu klasy jako argumentu i używam go do sprawdzania atrybutów.Ruby on Rails Case/Switch. Jak dopasować do obiektu?

Na przykład

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

Jedynym problemem jest to, że nie działa.

Co działa to:

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

Wszelkie porady, w jaki sposób można przejść o sprawdzenie, czy obiekt użytkownika jest zakazane lub zablokowane za pomocą przełącznika?

Dziękuję

Odpowiedz

19

Zrób user.status metodę, która zwraca stan użytkownika, to można to zrobić:

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

Dziękuję za wszystkie odpowiedzi. Uważam, że odpowiedź Zepplocka jest najbardziej użyteczna dla mojej aplikacji. Jedyna różnica polega na tym, że użyłem symboli w metodzie i przypadku. Oto metoda pisałem: stan def jeśli self.ban zwrot: zakaz koniec jeśli self.lock zwrot: zablokowanie koniec końcowy – Brian

+0

@Brian: Wystarczy Rubify trochę - jeśli funkcja zwraca wartość logiczną, dobrze jest nazwać je znakiem zapytania. Ponadto, nawet jeśli post-modyfikatory mogą być nadużywane i szkodzą czytelności, w tym przypadku myślę, że pracują nad poprawą: 'def status; return: zbanowany, jeśli zbanowany ?; return: zablokowany, jeśli jest zablokowany? end' – Amadan

0

można zrobić jak Zepplock powiedział. Ale dla danego przykładu poniżej jest najlepszy sposób (tylko przykład)

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

Podoba mi się odpowiedź @ Salila; Jednakże, jeśli naprawdę podoba case, można to zrobić:

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

UPDATE Jörg powiedział to działa zbyt, i ma rację! Daj mu trochę głosów na swoją odpowiedź! (Jak ja)

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

UPDATE 2012 Działa to teraz:

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

+1, ponieważ nigdy nie myślisz, aby użyć prawdziwego jako warunek sprawy. – Salil

+0

Zgaduję, że kolejność numerów when jest całkiem ważna, prawda? W każdym razie +1 za tak niesamowity pomysł. –

+3

Jest to niepotrzebnie skomplikowane. Powodem, dla którego to działa, jest "true === true". Ale druga forma wyrażenia "case", czyli po prostu pomijanie "prawdziwego" w ogóle, już robi to samo. –

0

@Brian idea przypadku przełącznika jest to, że masz zmienną, która przyjmuje wartość dynamiczną i sprawdza go przeciwko kilku stałym zestawom wartości. W napisanym fragmencie kodu instrukcje case zawierają wartości dynamiczne, takie jak user.ban, które zależą od samej zmiennej, którą próbujesz sprawdzić. Prawidłowy sposób użycia przełącznika to sposób demonstracji @Zepplock.

2

Lol, kocham odpowiedź Amadana. A jeśli naprawdę potrzebujesz instrukcji case, prawdopodobnie powinieneś robić to, co powiedział Zepplock (chociaż może rozważyć symbole zamiast napisów), ale na podstawie twojego przypadku użycia, potrzebujesz bardziej opartego na twierdzeniu rozwiązania, takiego jak Salil.

W każdym razie, pomyślałem, że też się poddam i dobrze się bawię^_^ Oto rozwiązanie, które będzie działało z tym, co powiedziałeś, tworzy obiekty, które reagują na === (jakie użycie instrukcji używa), a następnie wywołują metodę zainteresowania (blokowanie lub blokowanie) i zwracają ją. powinieneś umieścić je w jakimś config lub inicjatora, lub w inny sposób przechowywać wyniki po pierwszym wywołaniu, w celu zaoszczędzenia wydajności (tylko aplikacja potrzebuje do tworzenia tych obiektów jeden raz)

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 

Uwaga: ja "Nie zalecam tego rozwiązania, ponieważ narusza ono hermetyzację. Zablokowane powinno być zdefiniowane i użyte dla twojego użytkownika, ale aby to zadziałało, musi być zdefiniowane w otaczającym zakresie.I przede wszystkim przyniesie to dla zabawy :)

7

Wystarczy pominąć user:

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

w Ruby, istnieją dwie formy ekspresji case. W powyższym formularzu wykonuje on po prostu pierwszą gałąź, która ocenia do wartości truish (tj. Cokolwiek z wyjątkiem nil lub false).

Druga forma

case foo 
when bar 
    baz 
end 

jest równoważna

if bar === foo 
    baz 
end