2011-10-06 22 views
8

Recientemente he tenido algunos problemas para conseguir que una ruta funcione correctamente. La solución resultó ser simple, pero tuve un problema inesperado que me impidió llegar a ella. La siguiente línea, incluido en una plantilla erb, funciona a la perfección:Espaciado entre paréntesis en Ruby

<%= button_to "Confirm delivery", delivery_confirm_path(@delivery) %> 

Ésta no:

<%= button_to "Confirm delivery", delivery_confirm_path (@delivery) %> 

Parece separación antes del paréntesis de apertura no está permitido en este caso. El error que recibo es este:

/app/views/deliveries/_delivery_buttons.html.erb:22: syntax error, 
unexpected tLPAREN_ARG, expecting keyword_do or '{' or '(' 
...ivery", delivery_confirm_path (@delivery));@output_buffer... 
...        ^

¿Alguien puede explicar por qué esto causa un error?

EDIT: para obtener información, esto es de Ruby 1.9.2 y 3.0.9 Carriles, en Windows 7 de 64 bits

+2

http://www.justskins.com/forums/ruby-1-8-space-122361.html – Gazler

+0

parece como una limitación de la lengua. Encontraste una solución alternativa, no veo por qué tienes que ponerlo como una pregunta. – Candide

+0

@Gazler +1, excelente enlace con una publicación del propio Matz! –

Respuesta

6

Cualquier persona que pone un espacio antes de un parámetro de la lista de paréntesis, consigue lo que se merecen, digo!

El problema es que está cerrando la llamada a button_to en el segundo ejemplo (espacio antes del paréntesis) y no sabe qué hacer a continuación.

+0

En su comentario a la respuesta de Sebastien, usted menciona que está documentado cuando puede usar un espacio. ¿Tienes algún enlace? El comentario de Gazler se relaciona con una respuesta bastante definitiva de Matz, pero no he visto dónde esté documentado que el espaciado sea importante. – asc99c

+1

@ asc99c Me refería al libro de O'Reilly The Ruby Programming Language, sección 2.1.6.2, "Espacios e invocaciones de métodos".La regla general: no coloque un espacio antes de un método y su paren de apertura :) No habla en el libro de por qué, y proporciona un ejemplo de ruptura diferente. –

-1

No se puede utilizar un espacio entre una función y sus argumentos. De hecho, en los rieles, el motor del analizador quiere el paréntesis de la función justo después de su llamada. Esa es la vida de los rieles.

Espero poder ayudarte.

Gracias

+1

¿No es la "vida del rubí"? – christianblais

+4

Esto no es correcto; las * circunstancias * bajo las cuales puede, y no puede, usar un espacio, están documentadas. 'puts (" hi ")', por ejemplo, funciona bien. –

+0

** Puedes ** usar un espacio entre una función y sus argumentos, en Ruby, y también en Rails. Estos todos producen la misma salida: 'pone "hi"' 'puts ("hi")' 'puts ("hi")' 'pone "hi"' –

4

No estoy seguro de si así es como el analizador de ruby ​​realmente funciona, pero lo pienso de esta manera: La coma antes de delivery_confirm_path tiene mayor precedencia que los paréntesis, a menos que se deshaga del espacio.

que el intérprete ve la llamada al método como este:

button_to "Confirm delivery", delivery_confirm_path 

En otras palabras, delivery_confirm_path se analiza como una llamada de método sin argumentos. Pero luego el analizador ve el (@delivery) colgando y no es una sintaxis válida porque sigue la llamada al método button_to. Es como si tuvieras esta sintaxis no válida:

button_to("Confirm delivery", delivery_confirm_path) (@delivery) 

puede evitar el comas precedencia al hacer esto en su lugar:

button_to "Confirm delivery", (delivery_confirm_path (@delivery)) 

Pero por lo general es más fácil de quitar sólo el espacio.

El principio para recordar es que si hay un espacio antes de paréntesis con una llamada a un método, los paréntesis se utilizan como agrupación y no como paréntesis de llamada a método.

Aquí hay algunos ejemplos para ayudar. Yo uso el siguiente método en mis ejemplos:

def foo(*args); puts args.inspect; true; end 

Si estás en Ruby 1.9, sugiero encender las advertencias cuando se ejecutan los ejemplos: $-w = true. Esto mostrará warning: (...) interpreted as grouped expression si tiene espacio antes de paréntesis.

Estas dos líneas son sintácticamente equivalentes:

foo (1) 
foo 1 

Eso es porque (1) como una expresión agrupado es sólo 1.

¿De qué sirve la agrupación?

Una razón es solo para una mayor legibilidad. Puede considerar que es más fácil de entender con parens en esta expresión que sin:

foo (2 + 3) 
foo 2 + 3 

Otro motivo es la precedencia. Supongamos que tengo una operación de baja precedencia, como el operador and. Debido a que la llamada al método tiene una mayor prioridad, el and se evalúa después de la llamada. Esto imprime [2] y devuelve 3:

foo 2 and 3 # same as foo(2) and 3, i.e. true and 3 

Pero esto imprime [3] y devuelve true:

foo (2 and 3) # the grouped expr returns 3, which is passed to foo 

Tenga en cuenta, sin embargo, que el ejemplo and es un tanto artificial, porque rubí no permite la eliminación de los anteriores espacio. (No estoy seguro de por qué, ya que && está permitido en lugar de and). Pero se entiende la idea.

foo(2 and 3) # syntax error - but why?? I still don't understand. 
foo(2 && 3) # works fine. This is strangely inconsistent. 

Esto demuestra que la eliminación del espacio antes de una llamada al método elevará la precedencia método de guardia por encima de una coma:

foo 1, foo 2 # syntax error; the 2 is dangling 
foo 1, foo(2) # ok 

Otra Gotcha es la lista de argumentos.

foo 2, 3 # both are treated as args to the method call 
foo (2, 3) # syntax error, because "2, 3" is grouped as an expression, but is not a valid one 
Cuestiones relacionadas