6

I want a resource URI to look like this:

https://domain.tld/resource?param=foo&param=bar&param=baz

But Rails requires array query params to use the square bracket notation. Before URL escaping, the Rails equivalent of the above URI looks like this:

https://domain.tld/resource?param[]=foo&param[]=bar&param[]=baz

I can manually wrangle request.url inside of my controller, but I'd rather not do this ad-hoc if I can help it. Is there a standard way to support the first style of URI in Rails?

2 Answers 2

3

No standard way.

Any way I think it is not good idea to change it for whole rails application, because it breaks conventions (and probably some helpers).

Sign up to request clarification or add additional context in comments.

5 Comments

Several frameworks use that to indicate a collection of parameters, e.g., an array or a list.
I agree with @DaveNewton here, as does the Wikipedia article. "While there is no definitive standard, most web frameworks allow multiple values to be associated with a single field." en.wikipedia.org/wiki/Query_string
@SperanskyDanil Meh; AFAIC the important part of the answer is the "no standard way" part--I was just pointing out that the additional part isn't really correct. Not so wrong as to warrant downvotes IMO.
@SperanskyDanil I was a bit liberal with the downvote. Unfortunately, you can't "un-downvote." :\ I could upvote to neutralize.
@SperanskyDanil Good approach! :) I like your edited answer much better. FYI - my changes will be restricted to a specifically scoped group of controllers.
1

tl;dr

You can accomplish this with standard Ruby tools using the raw URL. I have the following helper method in my ApplicationController to support this:

# Support for flat array params, `URI#query` can return `nil`
def raw_params = CGI.parse(URI(request.url).query || "")

Major Caveat

I must support this as it's a requirement of many third party APIs. However, unless you have a compelling business need, I'd echo the strong recommendations to not deviate from conventions. It requires more work down the line and copious comments so I don't forget why I'm doing goofy looking things when I revisit the code.

Examples

Faraday requires a connection specifically for this:

Faraday.new(request: {params_encoder: Faraday::FlatParamsEncoder})

WebMock needs to be configured to support this:

WebMock::Config.instance.query_values_notation = :flat_array

Stubs cannot use the more descriptive syntax and work off a raw string:

# This is my working test because…
stub_request(:get, "https://domain.tld/resource?param=foo&param=bar")
  .to_return(…)

# this won't work as `WebMock will add `[]`s
stub_request(:get, "https://domain.tld/resource")
  .with(query: {param: ["foo", "bar"]})
  .to_return(…)

And finally, query params need to be manually constructed differently:

# I need to do
URI.encode_www_form({param: ["foo", "bar"]}) #=> "param=foo&param=bar"

# vs. pure Rails
{param: ["foo", "bar"]}.to_query #=> param%5B%5D=foo&param%5B%5D=bar

None of this is truly abhorrent and I still sleep well at night but conventions make things so much easier to work with and vastly decrease your cognitive load when coding.

Comments

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.