rails - ¿Por qué se usan los signos de exclamación en los métodos de Ruby?
ruby o php (10)
! normalmente significa que el método actúa sobre el objeto en lugar de devolver un resultado. Del libro Programación Ruby :
Los métodos que son "peligrosos", o que modifican el receptor, pueden nombrarse con un final "!".
En Ruby, algunos métodos tienen un signo de interrogación ( ?
) Que hace una pregunta como include?
que pregunta si el objeto en cuestión está incluido, esto luego devuelve un verdadero / falso.
Pero, ¿por qué algunos métodos tienen signos de exclamación ( !
) Donde otros no?
Qué significa eso?
Desde themomorohoax.com:
Una explosión puede utilizarse de las siguientes formas, en orden de mis preferencias personales.
1) Un método de registro activo genera un error si el método no hace lo que dice que hará.
2) Un método de registro activo guarda el registro o un método guarda un objeto (por ejemplo, ¡tira!)
3) Un método hace algo "extra", como publicar en algún lugar, o hacer algo de acción.
El punto es: solo use una explosión cuando realmente haya pensado si es necesario, para ahorrar a otros desarrolladores la molestia de tener que comprobar por qué está utilizando una explosión.
La explosión proporciona dos señales a otros desarrolladores.
1) que no es necesario guardar el objeto después de llamar al método.
2) Cuando se llama al método, se cambiará la db.
http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods
El signo de exclamación significa muchas cosas, y a veces no se puede decir mucho más que "esto es peligroso, tenga cuidado".
Como han dicho otros, en los métodos estándar a menudo se usa para indicar un método que causa que un objeto se mute a sí mismo, pero no siempre. Tenga en cuenta que muchos métodos estándar cambian su receptor y no tienen un signo de exclamación ( pop
, shift
, clear
), y algunos métodos con signos de exclamación no cambian su receptor ( exit!
). Vea este artículo por ejemplo.
Otras bibliotecas pueden usarlo de manera diferente. En Rails, un signo de exclamación a menudo significa que el método lanzará una excepción en caso de falla en lugar de fallar en silencio.
Es una convención de nomenclatura, pero muchas personas la usan de maneras sutilmente diferentes. En su propio código, una buena regla de oro es usarlo siempre que un método esté haciendo algo "peligroso", especialmente cuando existen dos métodos con el mismo nombre y uno de ellos es más "peligroso" que el otro. "Peligroso" puede significar casi cualquier cosa sin embargo.
En general, los métodos que terminan en !
Indica que el método modificará el objeto al que se llama . Ruby llama a estos métodos " peligrosos " porque cambian el estado al que otra persona podría tener una referencia. Aquí hay un ejemplo simple para cadenas:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
Esto dará como resultado:
a string
En las bibliotecas estándar, hay muchos lugares donde verás pares de métodos con nombres similares, ¡uno con el !
y uno sin. Los que no tienen se llaman "métodos seguros" y devuelven una copia del original con los cambios aplicados a la copia , sin cambiar el destinatario. Aquí está el mismo ejemplo sin el !
:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn''t modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
Esto produce:
A STRING
a string
Tenga en cuenta que esto es solo una convención, pero muchas clases de Ruby lo siguen. También le ayuda a realizar un seguimiento de lo que se está modificando en su código.
En pocas palabras:! los métodos simplemente cambian el valor del objeto al que se les llama, mientras que un método sin !
devuelve un valor manipulado sin escribir sobre el objeto al que se recurrió el método.
¡Solo usa !
si no planea necesitar el valor original almacenado en la variable a la que llamó el método.
Prefiero hacer algo como:
foo = "word"
bar = foo.capitalize
puts bar
O
foo = "word"
puts foo.capitalize
En lugar de
foo = "word"
foo.capitalize!
puts foo
Por si acaso me gustaría volver a acceder al valor original.
Es más exacto decir que los métodos con un Bang! Son las versiones más ruby-forum.com/topic/176830#773946 o surprising . Hay muchos métodos que mutan sin un Bang, como .destroy
y en general los métodos solo tienen bangs donde existe una alternativa más segura en la biblioteca central.
Por ejemplo, en Array tenemos .compact
y .compact!
, ambos métodos mutan la matriz, pero .compact!
devuelve nil en lugar de self si no hay nil''s en la matriz, lo que es más sorprendente que solo devolver self.
¡El único método no mutante que he encontrado con un bang es el Kernel
de Kernel
.exit!
lo que es más sorprendente que .exit
porque no puede detectar SystemExit
mientras se está cerrando el proceso.
Rails y ActiveRecord continúan esta tendencia en el sentido de que usan bang para obtener efectos más ''sorprendentes'' como .create!
lo que plantea errores en caso de fallo.
Esta convención de nomenclatura se levanta de Scheme .
1.3.5 convenciones de nombres
Por convención, los nombres de procedimientos que siempre devuelven un valor booleano usualmente terminan en ``? ''''. Tales procedimientos se llaman predicados.
Por convención, los nombres de los procedimientos que almacenan valores en ubicaciones previamente asignadas (consulte la sección 3.4) generalmente terminan en ``! ''''. Tales procedimientos se llaman procedimientos de mutación. Por convención, el valor devuelto por un procedimiento de mutación no está especificado.
Explicación simple:
foo = "BEST DAY EVER" #assign a string to variable foo.
=> foo.downcase #call method downcase, this is without any exclamation.
"best day ever" #returns the result in downcase, but no change in value of foo.
=> foo #call the variable foo now.
"BEST DAY EVER" #variable is unchanged.
=> foo.downcase! #call destructive version.
=> foo #call the variable foo now.
"best day ever" #variable has been mutated in place.
Pero si alguna vez downcase!
un método downcase!
En la explicación anterior, foo
cambiaría a downcase permanentemente. downcase!
no devolvería un nuevo objeto de cadena, sino que reemplazaría la cadena en su lugar, cambiando totalmente la foo
a downcase. Te sugiero que no uses el downcase!
A menos que sea totalmente necesario.
Llamados "Métodos destructivos" Tienden a cambiar la copia original del objeto al que se refiere.
numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers # returns [nil,nil,nil,nil,nil]
!
Me gusta pensar en esto como un cambio explosivo que destruye todo lo que ha pasado antes. Un signo de exclamación significa que está haciendo un cambio guardado permanente en su código.
Si utiliza, por ejemplo, el método de Ruby para la sustitución global de gsub!
La sustitución que hagas es permanente.
Otra forma de imaginarlo es abrir un archivo de texto y buscar y reemplazar, y luego guardar. !
hace lo mismo en tu codigo
Otro recordatorio útil si vienes del mundo bash es que sed -i
tiene este efecto similar de hacer un cambio guardado permanente.