Überprüfen Sie, ob in der Rails-Verknüpfung nicht null und nicht leer ist.

74

Ich habe eine Show-Seite für meine Benutzer und jedes Attribut sollte nur auf dieser Seite sichtbar sein, wenn es nicht null und keine leere Zeichenfolge ist. Unten habe ich meinen Controller und es ist ziemlich ärgerlich, @user.city != nil && @user.city != ""für jede Variable die gleiche Codezeile schreiben zu müssen . Ich bin nicht sehr vertraut mit dem Erstellen eigener Methoden, aber kann ich irgendwie eine Verknüpfung erstellen, um so etwas zu tun : @city = check_attr(@user.city)? Oder gibt es eine bessere Möglichkeit, dieses Verfahren zu verkürzen?

users_controller.rb

def show 
  @city = @user.city != nil && @user.city != ""
  @state = @user.state != nil && @user.state != ""
  @bio = @user.bio != nil && @user.bio != ""
  @contact = @user.contact != nil && @user.contact != ""
  @twitter = @user.twitter != nil && @user.twitter != ""
  @mail = @user.mail != nil && @user.mail != ""
end
user3048402
quelle

Antworten:

196

Es gibt eine Methode, die dies für Sie erledigt:

def show
  @city = @user.city.present?
end

Die present?Methode testet auf Nicht- nilPlus hat Inhalt. Leere Zeichenfolgen, Zeichenfolgen, die aus Leerzeichen oder Tabulatoren bestehen, gelten als nicht vorhanden.

Da dieses Muster so häufig vorkommt, gibt es in ActiveRecord sogar eine Verknüpfung:

def show
  @city = @user.city?
end

Dies ist ungefähr gleichwertig.

Das Testen von vs nilist fast immer redundant. In Ruby gibt es nur zwei logisch falsche Werte: nilund false. Wenn eine Variable nicht wörtlich sein kann false, ist dies ausreichend:

if (variable)
  # ...
end

Dies ist dem Üblichen if (!variable.nil?)oder dem, if (variable != nil)was gelegentlich auftaucht, vorzuziehen . Ruby tendiert dazu, einen reduktionistischeren Ausdruck zu bevorzugen.

Ein Grund, warum Sie mit vs. vergleichen möchten, nilist, wenn Sie eine Drei-Zustands-Variable haben, die sein kann true, falseoder wenn Sie nilzwischen den letzten beiden Zuständen unterscheiden müssen.

Tadman
quelle
9
Beachten Sie, dass Sie ab Ruby 2.3.0 viele redundante Nullprüfungen mit dem einsamen Operator if @user && @user.authenticatedif @user&.authenticated
1
Ein weiterer Grund , warum Sie wollen würde tun if object.present?über if object, wenn Sie das Objekt später in Dekorateur wickeln, wäre das Ergebnis ändern , wenn Sie verwendet .present?. philihp.com/2018/prefer-if-object-present-over-if-object.html
Philihp Busby
12

Sie können .present verwenden? welches in ActiveSupport enthalten ist.

@city = @user.city.present?
# etc ...

Sie könnten es sogar so schreiben

def show
  %w(city state bio contact twitter mail).each do |attr|
    instance_variable_set "@#{attr}", @user[attr].present?
  end
end

Es ist erwähnenswert, dass Sie verwenden können, wenn Sie testen möchten, ob etwas leer ist .blank?(dies ist das Gegenteil von .present?).

Auch nicht verwenden foo == nil. Verwenden Sie foo.nil?stattdessen.

Vielen Dank
quelle
@Mayank, das OP setzt eine Instanzvariable auf true/ falsevalue. reciever.present?gibt true zurück, wenn der receiverWert nicht leer ist. Weitere Erläuterungen finden Sie in den von mir verlinkten Dokumenten.
Vielen Dank, dass Sie
danke, ich habe deinen Standpunkt verstanden, aber ich kann nicht verstehen, wie instance_variable_set "@ # {attr}", @user [attr] .present? wird funktionieren..?
Neo-Code
@ Mayank, instance_variable_set("@foo", "bar")ist das gleiche wie @foo = "bar". Es ist nur eine programmatische Methode zum Festlegen von Instanzvariablen ^^
Vielen Dank
okz danke jetzt habe ich verstanden ... aber noch etwas was javascript: atob ("bmFreW90b0BnbWFpbC5jb20 ="); meint ?
Neo-Code
Mayank, führen Sie es in einer Javascript-Konsole aus, um es herauszufinden!
Vielen Dank, dass Sie