Case i include?

Może to jakaś banalna sprawa a może … nie wiem jak to ugryść :frowning:

code
roles = user.roles.map{|r| r.name}
if roles.include?(‘admin’)
admin_ability
elseif roles.include?(‘manager’)
manager_ability
(…)[/code]
Ponieważ trochę tych warunków jest to chciałbym wykorzystać case ale …

case user.roles.map{|r| r.name} when include?('admin') admin_ability when include?('manager') manager_ability (...)
Tutaj oczywiście dostaję błąd undefined method `include?’. Jak to powinno być poprawnie zapisane?

roles.each |role| do self.send (role+"_ability").to_sym end
Potraktuj jak pseudokod, ale w tym kierunku bym poszedł

Fakt, że robisz coś w ten sposób jest wskazówką, że design w którymś momencie źle poszedł. Zwykle tego właśnie jest oznaką długi case/when z podobnymi konstrukcjami w środku

Dzieki za odzew ale wasze odpowiedzi nie rozwiązują problemu.

@Tubis
Gdyby poszczególne przypadki były tylko tak proste jak podałem to faktycznie można by było iść w tym kierunku. A co jeśli dany przypadek będzie dotyczył sytuacji gdy dany użytkownik musie mieć równocześnie dwie role? A co gdy dany przypadek to nie tylko proste wywołanie jakiejś metody ale pewna sekwencja poleceń?

@paneq
Skąd wniosek, że to błąd? Problem dotyczy modelu Ability dla CanCan. Przecież muszę rozpisać wszystkie przewidywane role aplikacyjne.
W tej chwili mam cztery: admin, manager, teacher, student. Zastanawiam się jednak nad dodatkowymi bo np. “teacher” to nie koniecznie twórca kursu a z kolei twórca kursu nie koniecznie musi mieć dostęp do informacji o uczestnikach kursu więc przydałaby się dodatkowa rola np. “editor”. Widzisz lepsze rozwiązanie niż case lub if…elseif?

Poza tym interesuje mnie samo rozwiązanie tego typu problemu bo może on się pojawić również w innym miejscu aplikacji. Wszystkie manuale jakie znalazłem sprowadzają się do sytuacji gdy do case przekazywana jest pojedyncza wartość a w warunku mamy listę możliwości. Tymczasem tutaj przekazywana jest cała tablica. Znalazłem jedno rozwiązanie…

roles = user.roles case when roles.include?('admin') ...
Tyle tylko, że to właściwie jest to samo co if więc ani oszczędność klawiatury ani czytelność kodu.

Może to Ci w jakiś sposób pomoże http://mlomnicki.com/ruby/tricks-and-quirks/2011/02/10/ruby-tricks2.html

[quote=Tuptus]@paneq
Skąd wniosek, że to błąd? Problem dotyczy modelu Ability dla CanCan. Przecież muszę rozpisać wszystkie przewidywane role aplikacyjne.[/quote]
Co znaczy, że musisz rozpisać i czy to co robisz w kodzie który zacytowałeś to jest to “rozpisywanie” ?

Wniosek, że to błąd jest stąd, że zwykle taki kod sugeruje, że coś źle zostało zaprojektowane.

Przykładowo:

[code]class Costam
def jakas_metoda
if admin?
do_admin_stuff
elsif manager?
do_manager_stuff
else
do_user_stuff
end
end
end

Costam.new(‘admin’).jakas_metoda[/code]
Pewnie powinno zostać zrefaktoryzowany jakoś tak by można było napisać

[code]class Costam
def jakas_metoda
type.do_stuff
end
end

Costam.new(AdminType.new).jakas_metoda[/code]
czyli poprzez delegowanie do innego obiektu, który można podmieniać a który zawsze ma ten sam interfejs. Na tym mniej więcej polega programowanie obiektowe, że pozwala takich konstrukcji case when unikać poprzez delegowania.