2

Could you help me understand why the following code works:

def activity_params
  params.require(:activity).permit(:name, :description, :location, :user_id, category_ids: [])
end

Yet when I put the array somewhere in the middle instead of last, I get a syntax error:

def activity_params
  params.require(:activity).permit(:name, :description, :location, category_ids: [], :user_id)
end
3
  • 1
    Sorry Cary, I'm new on StackOverflow and still getting used to the community and what is considered good behaviour. Commented Dec 30, 2019 at 22:37
  • 1
    See the faq. Commented Dec 30, 2019 at 22:42
  • When asking a question like this, we want to know what effort you put into answering the question yourself: Did you research it? If so, what did you learn and why didn't it help? If you got an error, what was it? What did you learn when you looked it up? "Stack Overflow question checklist" will help. Go through that, then edit your question to improve it. Commented Dec 31, 2019 at 4:08

2 Answers 2

3

Ruby lets you skip a lot of punctuation that other languages require. In this case, Ruby is making some assumptions about your syntax that may not be obvious. Here's how it's being parsed:

permit(:name, :description, :location, :user_id, { :category_ids => [] })

permit is receiving 5 arguments: 4 symbols, and one hash. In arguments to methods, the last parameter can be a hash but without the hash literal notation of {}.

When you move that hash syntax to the middle of the argument list, it's no longer last, and therefore considered a syntax error.

Knowing this, I believe that if you make it an explicit hash, then it should work here:

permit(:name, :description, :location, { category_ids: [] }, :user_id)
Sign up to request clarification or add additional context in comments.

3 Comments

Blame the design of this API :) This work well in simple cases, but Rails uses this style in a few ways, and when it gets complicated, you really have to know how ruby parses this shit or you'll get confused fast.
Thanks this indeed works and now I understand why the former didn't. So do I understand correctly that for readability, it's considered good practice to move the hash syntax(es) to the end of the argument list?
Yeah, I'd say so. But it really depends. If that argument list is long and you break it up on multiple lines, have one of those lines be a hash and the rest be symbols, it should be plenty readable.
1

Keyword arguments (named arguments that end in a colon) must come after all positional arguments, as described in the Arguments documentation:

When mixing keyword arguments and positional arguments, all positional arguments must appear before any keyword arguments.

Your category_ids is a keyword argument and the others are symbols treated as positional arguments, which is why they all have to be first.

1 Comment

This method permit() doesn't use keyword arguments though... This isn't what's actually going on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.