2010-01-01 21 views
7

Używam gem Authlogic z Ruby on Rails i I zostały z wykorzystaniem następujących czynności, aby uzyskać identyfikator użytkownika, który jest aktualnie zalogowany:dwukrotnie ampersand w Ruby

current_user = UserSession.find 
id = current_user && current_user.record.id 

nie mam zrozumienia jak current_user & & current_user.record.id zwraca bieżący identyfikator użytkownika. Myślę, że to zwróci boolean. Czy ktoś może wyjaśnić, jak to działa?

Odpowiedz

8

Logiczne i powodujące zwarcie. Oznacza to, że jeśli konstrukt to X & & Y, a X jest fałszywe, to Y nigdy nie zostanie sprawdzone, ponieważ z pewnością będzie to fałsz.

Ten kod mówi, zasadniczo:

if (current_user is TRUE) { 
    id = current_user.record.id; 
] 

Oto niektóre wyjście konsola pokazując dostać drugą wartość, jeśli pierwsza jest prawdziwe:

irb(main):005:0> true && 9 
=> 9 

i nil jeśli pierwszy jest zerowa:

irb(main):008:0> nil && 9 
=> nil 
+0

Interesujące.W PHP i kilku innych językach często używałem wartości booleanValue = booleanExpression1 && booleanExpression2, a na podstawie oceny wyrażenia "i" wartość booleanValue zostanie odpowiednio ustawiona. Więc nie jest to możliwe z Ruby? –

+0

PHP i inne C-lubi zwarcie ich && s też. Gdy używasz wartości logicznych, wyniki są takie, jakich oczekujesz, ale gdy masz typy obiektów i typy dynamiczne, jesteś w strefie specyficznej dla języka. –

+0

Ponadto, jeśli X (current_user) jest fałszywe (zakładam, że oznacza to, że current_user nie jest ustawione - zero?), To id będzie ustawione na wartość false zamiast na int (wartość current_user.record.id)? –

18

Brak typu Boolean w języku Rubin; Ruby ma dość prosty pogląd na prawdę (a dokładniej, ma dość prosty widok na kłamstwo).

  • przedmiotem false, która jest pojedyncza wystąpienie FalseClass jest uważany falsy
  • obiektu nil, która jest pojedyncza wystąpienie NilClass jest falsy
  • każdy obiekt jest truey (w tym, oczywiście, obiekt true, który jest instancją singleton TrueClass)

[BTW: oznacza to, że wiele obiektów, które są uważane za falsy w innych językach, są rzeczywiście truthy w Ruby, jak całkowita 0, realnej wartości 0.0, pustym ciągiem, The pusta tablica, pusty hash, postać 'F']

Więc operatorów logicznych &&, ||, and i ornie zwracają wartości logiczne. Zamiast tego zwracają pierwszy obiekt, który określa wynik wyrażenia.

(Są również przyczyną zwarcia, co oznacza, że ​​oceniają tylko minimalne podwyrażenia, które są potrzebne do ustalenia wyniku wyrażenia. Tak więc alternatywnym sformułowaniem byłoby zwrócenie wyniku ostatniego wyrażenia który został oceniony, co z kolei jest analogiczne do tego, co robią bloki, metody, ciała klas i ciała modułów.)

Co to jest znaczy, aby zwrócić pierwszy obiekt, który określa wynik? To naprawdę proste: wynik wyrażenia

a && b 

jest truthy jeśli zarównoa i btruthy, w przeciwnym razie jest falsy. Tak więc, jeśli a jest falsy, to całkowicie znaczenia co b jest: wynik będzie falsy w obu kierunkach. Więc równie dobrze możemy po prostu zwrócić a. (Pamiętaj, że nie musi być false, może to również być nil a programista może chcieć wiedzieć, który z nich było.)

Jeżeli OTOH, a jest truthy (IOW jest ani nil ani false), to wynik całego wyrażenia jest wyłącznie zależne b: jeśli b jest truthy, cały wynik będzie truthy, w przeciwnym razie, jeśli b jest falsy, cały wynik będzie falsy. Tak więc równie dobrze możemy zwrócić samą siebie, zamiast najpierw przekonwertować ją na wartość logiczną.

|| i or są analogiczne lub bardziej precyzyjnie podwójny do && i and.

Ty pisał ten przykład: nawet nie

id = current_user && current_user.record.id 

Tutaj autor spodziewacurrent_user być wartość logiczna! Zamiast tego spodziewa się, że będzie to albo User lub nil. Ale to jest całkiem w porządku, ponieważ jest pewna, że ​​nadal mogą być używane w wyrażeniu Boolean.

Podstawową intencją jest to, że autor chce zapobiec zgłoszeniu wyjątku NoMethodError, jeśli próbuje wywołać #record na nil.

Alternatywnym sposobem wyrażania byłoby

id = current_user.record.id unless current_user.nil? 

Jeśli chcesz wszystkie drastyczne szczegóły, sprawdź rozdział 11.1 (strona 36) Draft ISO Ruby Specification lub plikiem wykonywalnym specyfikacji RubySpec project. (Here's the one for &&.)

Raz napisałem pure Ruby implementation of Ruby's Boolean operators and conditional expressions dla zabawy. Mięso z wykonań jest następujące: twomixins.

+0

może to być wpis w blogu :) – Dty

+1

@Dty: It * is *. Po prostu nie mam bloga ;-) –

+0

örg: czy mogę zapytać, co robisz, jeśli nie jesteś "programistą"? Wydaje ci się, że znasz bardzo dużo na "rekreacyjnego" programistę! ps. żałuję, że nie było sposobu na wysłanie wiadomości błyskawicznych na SO. – Dty