Se la stringa è vuota, restituisce un valore predefinito


93

Spesso ho bisogno di controllare se qualche valore è vuoto e scrivere "Nessun dato presente" in questo modo:

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

E quando abbiamo circa 20-30 campi che dobbiamo elaborare in questo modo, diventa brutto.

Quello che ho fatto è una classe String estesa con ormetodo

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

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

Adesso sta meglio. Ma è ancora grezzo e grezzo

Come sarebbe meglio risolvere il mio problema. Forse sarebbe meglio estendere ActiveSupport classo utilizzare il metodo di supporto o i mixin o qualsiasi altra cosa. Che idealogia Ruby, la tua esperienza e le migliori pratiche possono dirmi.

Risposte:


227

ActiveSupport aggiunge un presencemetodo a tutti gli oggetti che restituisce il suo ricevitore se present?(l'opposto di blank?) e nilaltrimenti.

Esempio:

host = config[:host].presence || 'localhost'

2
questo è fantastico. Sono preferibili le posizioni predefinite dei binari. Grazie!
fl00r

Innanzitutto è preferibile perché nella mia soluzione dovrei estendere almeno String, Fixnum e NilClass. E qui posso semplicemente usare un codice chiaro senza
bycles

12

Phrogz mi ha dato l'idea nel commento di PofMagicfingers, ma per quanto riguarda l'override di | anziché?

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

@user.address | "We don't know user's address"

2

Dato che lo stai facendo in Ruby on Rails, sembra che tu stia lavorando con un modello. Se desideri un valore predefinito ragionevole ovunque nella tua app, potresti (ad esempio) sostituire il addressmetodo per il tuo Usermodello.

Non conosco ActiveRecord abbastanza bene da fornire un buon codice per questo; in Sequel sarebbe qualcosa del tipo:

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

... ma per l'esempio sopra sembra che tu stia mescolando la logica di visualizzazione nel tuo modello, il che non è una buona idea.


Sì, è una cattiva idea impostare i valori predefiniti nei modelli :) Le mie forme piangeranno
fl00r

2

Il tuo metodo o potrebbe avere alcuni effetti collaterali indesiderati, poiché il valore alternativo (predefinito) viene sempre valutato, anche se la stringa non è vuota.

Per esempio

@user.address.or User.make_a_long_and_painful_SQL_query_here

farebbe un lavoro extra anche se l'indirizzo non è vuoto. Forse potresti aggiornarlo un po '(mi dispiace per aver confuso una riga, cercando di mantenerlo breve):

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 }

buona osservazione. Fatto. Ma perché verrà eseguito tutto il codice? guarda:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r

2
Verrà eseguito quando si effettua la chiamata originale, non con l'operatore ternario. Tutti gli argomenti verranno valutati sulla chiamata al metodo.
Tonttu

2

Probabilmente è meglio estendere ActiveRecord o singoli modelli invece di String.

A tuo avviso, potresti preferire uno schema più esplicito come

@user.attr_or_default :address, "We don't know the user's address"

Fa parte di Active Record? Nessun riferimento trovato.
cabe56

0

Rubino:

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

RoR:

unless my_str.blank? then my_str else 'default' end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.