Der Hauptvorteil - und der nur Vorteil, wenn Sie mich fragen - von einem case
/when
Block ist, dass die Bedingung in den case
genau einmal und nur einmal ausgeführt werden.
Also in diesem Fall:
case some_relatively_expensive_operation()
when :foo
# ...
when :bar
# ...
end
some_relatively_expensive_operation
wird nur einmal durchgeführt werden, während in diesem Fall:
if some_relatively_expensive_operation() == :foo
# ...
elsif some_relatively_expensive_operation() == :bar
# ...
end
some_relatively_expensive_operation()
läuft entweder einmal (wenn es :foo
) oder zweimal (wenn es ist etwas anderes).
Dies ist nur für die Leistung spielt keine Rolle, es macht auch die Bedingung leichter später zu ändern, da Sie nur so einmal und nicht wie viele if
/elsif
Blöcke haben Sie zu tun haben.
Offensichtlich funktioniert diese Struktur überhaupt nicht, wenn Sie mehrere Bedingungen testen möchten, die unterschiedlich sind - was Ihr aktueller Code tut. Ja, Sie können dies mit einem Lambda umgehen, was eine andere Antwort tut, aber dies vermisst völlig den Sinn dieses Konstrukts und ist wie das Einschlagen eines Nagels mit einem Hammer.
Also, was Sie tun müssen, ist eine Methode zum Objekt hinzufügen user
ist, die einen Wert mit der Rolle zurückgibt.Ich habe keinen Einblick in Ihrem User
Modell, aber dies könnte einfach sein:
class User
# [..]
def role
if is_admin?
:admin
else
:member
end
end
end
Wir haben immer noch für die besonderen Gast Erlaubnis, zu überprüfen, die vor die Haupt case
getan werden kann:
def self.permission_for(user)
# No current user - return Guest permissions
return GuestPermission.new unless user.current_user
case user.role
when :admin
AdminPermission.new(user)
when :member
MemberPermission.new(user)
end
end
Alternativ können Sie User.role
ändern, um :guest
zurückzugeben. Was auch immer Sie bevorzugen.
Jetzt werden Sie feststellen, dass diese Zeilen tatsächlich sehr ähnlich aussehen. Warum verwenden Sie hier überhaupt einen case
/when
Block? Können wir nicht einfach den Klassennamen von user.role
konstruieren? Ja wir können!
# Get instance to the class
klass = Object.const_get "#{user.role.to_s.capitalize}Permission"
# And create it!
klass.new user
Und wir können eine zweizeilige Methode dafür machen!
def self.permission_for(user)
return GuestPermission.new unless user.current_user
return Object.const_get("#{user.role.to_s.capitalize}Permission").new user
end
Oder auch nur eine Zeile, wenn User.role
kehrt :guest
, wenn es keine aktuellen Benutzer.
Es ist, weil 'user.is_admin?. ===' nicht definiert ist. – sawa
@Sawa - 'user.is_admin?' Ist definiert. Der gesamte Code von Ryan Bates funktioniert, und Sie können sehen, wo "elsif user.is_admin?" Im Arbeitscode enthalten ist. – Matteo