问题
In the book Rails Test Prescriptions (b10.0, page 176), there are examples of one-liner assertions like the following:
should "be successful" { assert_response :success }
This doesn’t appear to be valid ruby syntax to me, and ruby reports that the left curly brace is unexpected. In order for it to be parsed, I have to change it to
should "be successful"; do assert_response :success end
What's wrong with the syntax of the first example?
回答1:
This is valid Ruby syntax. Well, sort of. It just doesn't make sense!
Since the precedence of a literal block using curly braces is higher than passing an argument without parentheses, the block gets bound to the argument instead of the method call. If the argument is itself a method call, then you won't even get a syntax error. You'll just scratch your head wondering why your block doesn't get called.
To fix this, you either put parentheses around the argument, since parentheses have higher precedence than curly braces, or use the do
/ end
form, which is lower precedence than an argument list without parentheses.
def foo; yield if block_given?; 'foo' end
puts foo { puts 'block' }
# block
# foo
puts(foo) { puts 'block' }
# foo
puts foo do puts 'block' end
# foo
puts foo { puts 'block' }, foo { puts 'block' }
# block
# block
# foo
# foo
puts 'foo' { puts 'block' }
# SyntaxError: (irb):19: syntax error, unexpected '{', expecting $end
回答2:
This may be a mistake on my part in trying to get the example to take up fewer lines. The block is probably binding to the argument and not the method call, as Jorg said.
I think that the proper way to rewrite this as a one-liner is:
should("be successful") { assert_response :success }
But really, the way to go is to use the shoulda macro:
should respond_with(:success)
Thanks,
Noel
来源:https://stackoverflow.com/questions/4534436/one-liner-shoulda-syntax-using-braces