Wenn die Zeichenfolge leer ist, geben Sie einen Standardwert zurück

93

Oft muss ich überprüfen, ob ein Wert leer ist, und Folgendes schreiben: "Keine Daten vorhanden":

@user.address.blank? ? "We don't know user's address" : @user.address

Und wenn wir ungefähr 20-30 Felder haben, die wir auf diese Weise verarbeiten müssen, wird es hässlich.

Was ich gemacht habe, ist eine erweiterte String-Klasse mit orMethode

class String
  def or(what)
    self.strip.blank? ? what : self
  end
end

@user.address.or("We don't know user's address")

Jetzt sieht es besser aus. Aber es ist immer noch roh und rau

Wie wäre es besser, mein Problem zu lösen. Vielleicht wäre es besser, die ActiveSupport classHilfsmethode oder Mixins oder irgendetwas anderes zu erweitern oder zu verwenden. Welche Ruby-Idealogie, Ihre Erfahrung und Ihre Best Practices mir sagen können.

fl00r
quelle

Antworten:

227

ActiveSupport fügt presenceallen Objekten eine Methode hinzu , die ihren Empfänger zurückgibt, wenn present?(das Gegenteil von blank?), und nilansonsten.

Beispiel:

host = config[:host].presence || 'localhost'
David Phillips
quelle
2
das ist cool. Standardschienenmöglichkeiten werden bevorzugt. Danke!
Fl00r
Erstens wird es bevorzugt, weil ich in meiner Lösung String, Fixnum und NilClass mindestens erweitern sollte. Und hier kann ich einfach klaren Code ohne Bycles verwenden
fl00r
12

Phrogz gab mir die Idee in PofMagicfingers Kommentar, aber was ist mit dem Überschreiben von | stattdessen?

class String
  def |(what)
    self.strip.blank? ? what : self
  end
end

@user.address | "We don't know user's address"
Matt Briggs
quelle
2

Da Sie dies in Ruby on Rails tun, scheint es, als würden Sie mit einem Modell arbeiten. Wenn Sie überall in Ihrer App einen angemessenen Standardwert wünschen, können Sie beispielsweise die addressMethode für Ihr UserModell überschreiben .

Ich kenne ActiveRecord nicht gut genug, um dafür guten Code bereitzustellen. in der Fortsetzung wäre es so etwas wie:

class User < Sequel::Model
  def address        
    if (val=self[:address]).empty?
      "We don't know user's address"
    else
      val
    end
  end
end

... aber für das obige Beispiel scheint dies, als würden Sie die Ansichtslogik in Ihr Modell mischen, was keine gute Idee ist.

Phrogz
quelle
Ja, es ist eine schlechte Idee, Standardeinstellungen in Modellen
festzulegen
2

Ihre oder Methode kann einige unerwünschte Nebenwirkungen haben, da der alternative (Standard-) Wert immer ausgewertet wird, auch wenn die Zeichenfolge nicht leer ist.

Beispielsweise

@user.address.or User.make_a_long_and_painful_SQL_query_here

würde zusätzliche Arbeit machen, selbst wenn die Adresse nicht leer ist. Vielleicht könnten Sie das ein bisschen aktualisieren (Entschuldigung, dass Sie den Einzeiler verwirrt haben und versuchen, ihn kurz zu halten):

class String
  def or what = ""
    self.strip.empty? ? block_given? ? yield : what : self
  end
end

@user.address.or "We don't know user's address"
@user.address.or { User.make_a_long_and_painful_SQL_query_here }
Tonttu
quelle
gute Bemerkung. Verstanden. Aber warum wird der gesamte Code ausgeführt? schauen Sie:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r
2
Es wird beim ursprünglichen Aufruf ausgeführt, nicht beim ternären Operator. Alle Argumente werden beim Methodenaufruf ausgewertet.
Tonttu
2

Es ist wahrscheinlich besser, ActiveRecord oder einzelne Modelle anstelle von String zu erweitern.

Aus Ihrer Sicht bevorzugen Sie möglicherweise ein expliziteres Muster wie

@user.attr_or_default :address, "We don't know the user's address"
maxl0rd
quelle
Ist das Teil von Active Record? Es wurden keine Referenzen gefunden.
Cabe56
0

Rubin:

unless my_str.empty? then my_str else 'default' end

RoR:

unless my_str.blank? then my_str else 'default' end
Lucio
quelle