2011-01-27 8 views
81

A menudo tengo que comprobar si un valor está en blanco y escribir que "no los datos presentes" así:cadena está vacía luego regresar algún valor por defecto

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

Y cuando tenemos unos 20-30 campos que tenemos que procesar de esta manera se vuelve feo.

Lo que he hecho es extendido clase String con or mé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 class o utilizar el método de ayuda o mixins o cualquier otra cosa. Lo que la idealogía de rubí, tu experiencia y tus mejores prácticas pueden decirme.

Respuesta

208

ActiveSupport agrega un método presence a todos los objetos que devuelve su receptor si present? (lo contrario de blank?), y nil en caso contrario.

Ejemplo:

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

esto es genial. Se prefieren las posibilidades de los rieles por defecto. Gracias! – fl00r

+0

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

2

Dado que estás haciendo esto en Ruby on Rails, parece que estás trabajando con un modelo. Si quería un valor predeterminado razonable en todas partes en su aplicación, podría (por ejemplo) anular el método address para su modelo User.

No conozco ActiveRecord lo suficiente como para proporcionar un buen código para esto; en Sequel sería algo así 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 esto parece que estaría mezclando vista lógica en su modelo, que no es una buena idea.

+0

Sí, es mala idea para establecer los valores predeterminados en los modelos :) Mis formas llorarán – fl00r

12

Phrogz me dio una idea en el comentario de PofMagicfingers, pero ¿qué pasa con la anulación? ¿en lugar?

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

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

divertido :) me gusta – fl00r

2

Su método o podría tener algunos efectos secundarios no deseados, ya que el valor (predeterminado) alternativo 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 que el trabajo extra, incluso si la dirección no está vacío. Tal vez usted podría actualizar que un poco (lo de confundir una sola línea, tratando de que sea 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 } 
+0

buena observación. Lo tengo. Pero, ¿por qué todo el código se ejecutará? mira: 'a = 2; a == 2?"ok": @b = 3; @segundo; # => nil' – fl00r

+2

Se ejecutará al hacer la llamada original, no con el operador ternario. Todos los argumentos serán evaluados en la llamada al método. – Tonttu

+1

+1 por ser flojo –

2

Probablemente es mejor para extender modelos ActiveRecord o individuales en lugar de cadena.

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

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

Interesante manera. – fl00r

+0

¿Esto es parte de Active Record? No encontré ninguna referencia. – cabe56

Cuestiones relacionadas