2012-09-14 26 views
23

Tengo una cadena en Ruby en la que estoy llamando al método strip para eliminar el espacio en blanco inicial y final. p.ej.Ruby check if nil before calling method

s = "12345 " 
s.strip 

Sin embargo, si la cadena está vacía, aparece el siguiente error.

NoMethodError: método `strip' no definido para nada: NilClass

estoy usando Ruby 1.9 así que cuál es la forma más sencilla de comprobar si el valor es nulo antes de llamar al método de la tira?

Actualización:

He intentado esto en un elemento en una matriz, pero tengo el mismo problema:

data[2][1][6].nil? ? data[2][1][6] : data[2][1][6].split(":")[1].strip 
+1

esto se ha preguntado de una u otra manera docenas de veces: http://stackoverflow.com/questions/5429790/is-there-a-clean-way-to-avoid-calling-a-method-on- nil-in-a-nested-params-hash – tokland

+1

nota para el cartel original: la Cadena no está vacía como usted afirma, que sería 's =" "', es nula. Todavía no existe. Si estaba vacío, puede verificar con: 's.strip a menos que esté vacío' ' – three

+1

Si la cadena está vacía, no obtendrá ese error. – sawa

Respuesta

0

En pocas palabras:

s = s.nil? ? s : s.strip 

tl; dr Comprobar si s es nulo, luego devuelve s, de lo contrario, despréndalo.

+0

@lukad tiene una respuesta más simple que esta aunque. – Eugene

+0

Gracias - Acabo de probar esto en un elemento dentro de una matriz combinada con división. Sin embargo, todavía parece fallar: . pone datos [2] [1] [6] .nil? ? datos [2] [1] [6]: datos [2] [1] [6] .split (":") [1] .strip . NoMethodError: método indefinido 'strip 'for nil: NilClass – user1513388

+0

¿Qué devuelve' data [2] [1] [6] .split (":") 'return? Parece que solo tiene un artículo. – lukad

4

supongo que el método más fácil sería la siguiente:

s.strip if s 
+2

No es realmente conveniente si intenta encadenar cosas. –

+0

Lo que se necesita es una forma de decir universalmente: "Si llamo a un método en nil, simplemente devuelva nil" para que no tengamos que saturar nuestro código con estas cosas. IOW, necesitamos la funcionalidad de "lenguaje de scripting". Tal vez arrojar algo a la consola en el nivel de desarrollo, solo para ayudar a resolver problemas si/nula inesperadamente. – JosephK

+0

@JosephK Vea la respuesta de Jessie Sielaff. Lo que estás buscando se agregó en Ruby 2.3. Se llama el _operador de navegación seguro_. – lukad

1

método que funciona para mí (lo sé, nunca debería contaminar prístina espacio Object, pero es muy conveniente que voy a tomar un riesgo):

class Object 
    def unless_nil(default = nil, &block) 
    nil? ? default : block[self] 
    end 
end 

p "123".unless_nil(&:length) #=> 3 
p nil.unless_nil("-", &:length) #=> "-" 

En su caso particular podría ser:

data[2][1][6].unless_nil { |x| x.split(":")[1].unless_nil(&:strip) }

12

Puede utilizar el método de try ActiveSupport (biblioteca Rails)

gem install activesupport 

require 'active_support/core_ext/object/try' 
s.try(:strip) 

o puede utilizar mi joya tryit que da servicio amplio:

gem install tryit 

s.try { strip } 
2

ActiveSupport viene con un método para que: try. Por ejemplo, an_object.try :strip devolverá nil si an_object es nulo, pero procederá de otra manera. La sintaxis es la misma que send. Cf active_support_core_extensions.html#try.

1

Si se quiere evitar el error que aparece en la pregunta: ¿

s.to_s.strip 
8

Si no te importa el objeto adicional de ser creados, ninguno de estos trabajos:

"#{s}".strip 
s.to_s.strip 

Sin adicional objeto:

s && s.strip 
s.strip if s 
47

Rubí 2.3.0 añade un operador navegación segura (&.) que comprueba nulo antes de llamar a un método.

s&.strip 

Volverá nil si es snil, en lugar de aumentar NoMethodError.

+0

Sí, esta es la única manera de hacer que Ruby actúe como un lenguaje de scripting web adecuado. Si solo hubiera una manera de establecer esto globalmente para todos los casos donde aparece este comportamiento molesto e inútil, y para "convertir implícitamente" todos los valores a cadenas de manera predeterminada, cuando sea necesario (como las declaraciones puts). – JosephK

+1

Primera vez que he visto esto- muy útil – Yarin