Si la cadena está vacía, devuelve algún valor predeterminado

93

A menudo necesito verificar si algún valor está en blanco y escribir que "No hay datos presentes" así:

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

Y cuando tenemos entre 20 y 30 campos que necesitamos procesar de esta manera, se vuelve feo.

Lo que hice es una clase String extendida con ormétodo

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

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

Ahora se ve mejor. Pero todavía es crudo y áspero

Cómo sería mejor resolver mi problema. Tal vez sería mejor extender ActiveSupport classo usar el método auxiliar o mixins o cualquier otra cosa. Lo que ruby ​​idealogy, su experiencia y sus mejores prácticas me pueden decir.

fl00r
fuente

Respuestas:

228

ActiveSupport agrega un presencemétodo a todos los objetos que devuelve su receptor si present?(lo contrario de blank?) y de lo nilcontrario.

Ejemplo:

host = config[:host].presence || 'localhost'
David Phillips
fuente
2
esto es genial. Se prefieren las posibilidades de rieles predeterminados. ¡Gracias!
fl00r
En primer lugar, se prefiere porque en mi solución debería extender String, Fixnum y NilClass al menos. Y aquí puedo usar código claro sin bycles
fl00r
12

Phrogz me dio la idea en el comentario de PofMagicfingers, pero ¿qué pasa con anular | ¿en lugar?

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

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

Como está haciendo esto en Ruby on Rails, parece que está trabajando con un modelo. Si quisiera un valor predeterminado razonable en todas partes de su aplicación, podría (por ejemplo) anular el addressmétodo para su Usermodelo.

No conozco ActiveRecord lo suficientemente bien como para proporcionar un buen código para esto; en Sequel sería algo como:

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

... pero para el ejemplo anterior, parece que estaría mezclando la lógica de vista en su modelo, lo cual no es una buena idea.

Phrogz
fuente
Sí, es una mala idea establecer valores predeterminados en los modelos :) Mis formularios
llorarán
2

Su método o puede tener algunos efectos secundarios no deseados, ya que el valor alternativo (predeterminado) siempre se evalúa, incluso si la cadena no está vacía.

Por ejemplo

@user.address.or User.make_a_long_and_painful_SQL_query_here

haría un trabajo extra incluso si la dirección no está vacía. Tal vez puedas actualizar eso un poco (perdón por confundir una línea, tratando de ser 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 }
Tonttu
fuente
buen comentario. Entendido. Pero, ¿por qué se ejecutará todo el código? mirar:a=2 ; a == 2 ? "ok" : @b = 3 ; @b; #=> nil
fl00r
2
Se ejecutará al realizar la llamada original, no con el operador ternario. Todos los argumentos se evaluarán en la llamada al método.
Tonttu
2

Probablemente sea mejor extender ActiveRecord o modelos individuales en lugar de String.

En su opinión, es posible que prefiera un patrón más explícito como

@user.attr_or_default :address, "We don't know the user's address"
maxl0rd
fuente
¿Es esto parte de Active Record? No encontré ninguna referencia.
cabe56
0

Rubí:

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

RoR:

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