Si la chaîne est vide, renvoie une valeur par défaut

93

Souvent, je dois vérifier si une valeur est vide et écrire que "Aucune donnée présente" comme ça:

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

Et quand nous avons environ 20-30 champs que nous devons traiter de cette manière, cela devient moche.

Ce que j'ai fait est une classe String étendue avec une orméthode

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

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

Maintenant, ça va mieux. Mais c'est toujours brut et rugueux

Comment il serait préférable de résoudre mon problème. Il serait peut-être préférable d'étendre ActiveSupport classou d'utiliser une méthode d'assistance ou des mixins ou autre chose. Ce que l'idealogy ruby, votre expérience et vos meilleures pratiques peuvent me dire.

fl00r
la source

Réponses:

227

ActiveSupport ajoute une presenceméthode à tous les objets qui renvoie son récepteur si present?(l'opposé de blank?), et nilautrement.

Exemple:

host = config[:host].presence || 'localhost'
David Phillips
la source
2
c'est cool. Les positions par défaut des rails sont préférées. Merci!
fl00r
Tout d'abord, il est préféré car dans ma solution, je devrais au moins étendre String, Fixnum et NilClass. Et ici, je peux simplement utiliser du code clair sans bycles
fl00r
12

Phrogz m'a en quelque sorte donné l'idée dans le commentaire de PofMagicfingers, mais qu'en est-il du dépassement | au lieu?

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

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

Puisque vous faites cela dans Ruby on Rails, il semble que vous travaillez avec un modèle. Si vous souhaitez une valeur par défaut raisonnable partout dans votre application, vous pouvez (par exemple) remplacer la addressméthode de votre Usermodèle.

Je ne connais pas assez bien ActiveRecord pour fournir un bon code pour cela; dans Sequel, ce serait quelque chose comme:

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

... mais pour l'exemple ci-dessus, il semble que vous mélangiez la logique de vue dans votre modèle, ce qui n'est pas une bonne idée.

Phrogz
la source
Oui, c'est une mauvaise idée de définir des valeurs par défaut dans les modèles :) Mes formulaires vont pleurer
fl00r
2

Votre méthode ou peut avoir des effets secondaires indésirables, car la valeur alternative (par défaut) est toujours évaluée, même si la chaîne n'est pas vide.

Par exemple

@user.address.or User.make_a_long_and_painful_SQL_query_here

ferait un travail supplémentaire même si l'adresse n'est pas vide. Vous pourriez peut-être mettre à jour cela un peu (désolé de confondre one-liner, en essayant de rester bref):

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
la source
bonne remarque. Je l'ai. Mais pourquoi tout le code sera-t-il exécuté? regarder:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r
2
Il sera exécuté lors de l'appel d'origine, pas avec l'opérateur ternaire. Tous les arguments seront évalués lors de l'appel de méthode.
Tonttu le
2

Il est probablement préférable d'étendre ActiveRecord ou des modèles individuels au lieu de String.

À votre avis, vous préférerez peut-être un modèle plus explicite comme

@user.attr_or_default :address, "We don't know the user's address"
maxl0rd
la source
Cela fait-il partie d'Active Record? N'a trouvé aucune référence.
cabe56
0

Rubis:

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

RoR:

unless my_str.blank? then my_str else 'default' end
Lucio
la source