2011-10-06 52 views
8

我最近遇到了一些问题,导致路径正常工作。解决方案结果很简单,但我遇到了意想不到的问题,导致我无法实现。下面这行,包括在ERB模板,完美的作品:Ruby中圆括号的间距

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

这一个不:

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

看来前间距在这种情况下是不允许的左括号。我得到的错误是这样的:

/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... 
...        ^

任何人都可以解释为什么这会导致错误?

编辑:为信息,这是Ruby的1.9.2和Rails 3.0.9,在Windows 7 64位

+2

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

+0

似乎是一种语言的限制。你找到了一个解决方法,我不明白为什么你必须把它作为一个问题。 – Candide

+0

@Gazler +1,与Matz自己发布的贴子联系非常好! –

回答

6

任何人都认为把一个空间之前的参数列表括号得到他们应得的,我说的!

问题在于它在第二个示例(括号之前的空格)中关闭了对button_to的调用,并且不知道接下来要做什么。

+0

在你对塞巴斯蒂安的回答的评论中,你提到它被记录在可以使用空间的时候。你有任何链接? Gazler的评论链接到Matz的一个非常明确的答案,但我没有看到它被记录在哪里,间距很重要。 – asc99c

+1

@ asc99c我指的是O'Reilly的书“Ruby编程语言”,第2.1.6.2节“空间和方法调用”。一般规则:不要在方法和它的开头paren之前放置一个空格:)它不会在本书中讲述为什么,并提供了一个不同的破坏示例。 –

-1

不能使用的功能和它的参数之间的空间。事实上,在rails中,解析器引擎在调用之后需要函数的括号。 这就是铁轨的生命。

希望能帮到你。

谢谢

+1

难道不是“红宝石的生活”吗? – christianblais

+4

这是不正确的;记录下你可以或不可以使用空间的*情况*。例如,puts(“hi”)'可以正常工作。 –

+0

你可以**在函数和它的参数之间使用一个空格,在Ruby中也是如此,在Rails中也是如此。这些都产生相同的输出: '提出的 “hi”' '看跌期权( “HI”)' '看跌期权( “HI”)' '提出的 “hi”' –

4

我不确定这是ruby的解析器是如何工作的,但我认为它是这样的:除非你摆脱了空间,否则delivery_confirm_path之前的逗号比括号具有更高的优先级。

解析器看到该方法调用作为这样的:

button_to "Confirm delivery", delivery_confirm_path 

换句话说,delivery_confirm_path被解析为不带参数的一个方法调用。但是,然后解析器看到悬挂的(@delivery),它不是有效的语法,因为它遵循button_to方法调用。就好像你有这个无效的语法:

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

你可以这样做,而不是避免逗号优先级:

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

但它通常更容易只是删除空间。

要记住的原则是,如果在方括号括起来之前有一个空格,则括号用作分组,而不是方法调用括号。

下面是一些帮助的例子。我用下面的方法在我的例子:

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

如果你在Ruby 1.9的,我建议在警告打开运行例子的时候:$-w = true。如果括号前有空格,将显示warning: (...) interpreted as grouped expression

这两条线在语法上等价的:

foo (1) 
foo 1 

这是因为(1)为分组表达式仅仅是1

分组有什么用?

一个原因是为了更好的可读性。你可能会认为这更容易与括号理解这种表达与无:

foo (2 + 3) 
foo 2 + 3 

另一个原因是优先级。假设我有一个低优先级操作,如and操作符。由于方法调用的优先级较高,因此在调用后对and进行评估。这将打印[2]并返回3

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

但这打印[3]并返回true

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

但请注意,该and例子是人为的,因为红宝石不允许拆除前面的空间。 (我不知道为什么,因为允许&&而不是and。)但你明白了。

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

这表明一个方法调用之前移除所述空间将提升逗号上述方法调用的优先级:

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

另一个疑难杂症是参数列表。

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