Ancinek Ancinek - 3 months ago 7
Ruby Question

Ruby - passing block inside the function parenthesis

I have recently started to learn Ruby on Rails and it is really weird to get used to the syntax of Ruby.

I decided to go with all the parenthesis (that I know from other languages) that can be placed and I got stuck:

test "invalid signup information" do
get signup_path
assert_no_difference("User.count", {
user_params = { user: {
name: "",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar"
}}
post(user_path, {params: user_params})
})
end


I want to pass a block into the assert_no_difference and somehow it is showing me an error during my tests. It started to show it after I places the definition of user_params. As far as I read some websites the syntax is OK, so what might be going wrong?

Answer

There's two general forms for passing in blocks. The long-form way is to use do ... end:

assert_no_difference('User.count') do
  # ...
end

There's also the curly brace version:

assert_no_difference('User.count') {
  # ...
}

Note that the curly brace style is generally reserved for single line operations, like this:

assert_no_difference('User.count') { post(...) }

For multi-line you generally want to use do...end since it's easier to spot. The When in Rome principle applies here, so you may need to shed some of your expectations in order to do things the Ruby way.

What you're doing wrong is passing in an argument that's presumed to be a Hash, but as it contains arbitrary code that's invalid. Unlike JavaScript the block is defined outside of the arguments to function call.

Cleaning up your code yields this:

test "invalid signup information" do
  get signup_path

  assert_no_difference("User.count") do
    post(user_path,
      params: {
        user: {
          name: "",
          email: "foo@invalid",
          password: "foo",
          password_confirmation: "bar"
        }
      }
    )
  end
end

Note you can supply the arguments inline, plus any hash-style arguments specified as the last argument in a method call does not need its curly braces, they're strictly optional and usually best omitted.