3

I seem to be having the same problem as this chap here

I want to encode some parameters (for the import.io api). Effectively:

params = {
  :input => "webpage/url:http://www.example.com",
  :input => "keywords:some+keywords"

}

But that won't work, so I think this is the right approach:

params = { :input => ["webpage/url:http://www.example.com", "keywords:some+keywords"] }

and I want it to output

params.to_query
=> "input=webpage%2Furl%3Ahttp%3A%2F%2Fwww.example.com%2Fsome-id&input=keywords%3Asome%2Bkeywords"

unfortunately, I get

"input%5B%5D=webpage%2Furl%3Ahttp%3A%2F%2Fwww.example.com%2Fsome-id&input%5B%5D=keywords%3Asome%2Bkeywords"

It's adding [] after the input, which I believe is standard behaviour. How can I stop it doing it?

To clarify, what is the ruby or 'rails way' of dealing with url parameters that require duplicate keys?

Community
  • 1
  • 1
Carpela
  • 2,155
  • 1
  • 24
  • 55
  • Why do you want to stop it from doing it? That's a valid query param – Anthony Jan 15 '16 at 14:26
  • 1
    `[]` is how arrays are handled in params. If you want the end result to be the same as the start params you'll need those [] – Max Williams Jan 15 '16 at 14:28
  • The issue is that I can't call both of them "input" as the hash will just overwrite itself.. I need a way of passing to values, both with the key "input" to a set of query params that I'm going to pass into a URL. – Carpela Jan 15 '16 at 15:59
  • Anthony... I'm sure it is, but it's breaking the api. i.e. the api won't accept that as valid parameters. It is perfectly happy to accept variables with duplicate keys. Not my API so not something I can do anything about, other than to follow their rules.... – Carpela Jan 15 '16 at 16:00
  • Yes, input should be sent as an **array** of values. That's how we send multiple values. If your API doesn't accept it then it's pretty stupid. Are you sure that is the case? We can suggest hacky workarounds, but not knowing anything about the API it's hard to advise. – Max Williams Jan 15 '16 at 16:05
  • But, more helpfully, if your API doesn't like arrays, then you will need to structure the original data differently, in a way that the API expects. Otherwise you're asking "My API doesn't accept arrays, how can i send it an array?", which doesn't make sense as a question. – Max Williams Jan 15 '16 at 16:27
  • Here's the api. http://api.docs.import.io/ I'm not sure they're alone in this, but they definitely expect that query to come through with duplicate keys in it. – Carpela Jan 15 '16 at 16:28
  • Regarding, ‘If your API doesn't accept it then it's pretty stupid’: It’s Rails that interprets and emits parameter names using this bracket-based DSL. This is often very useful, but it’s not stupid for other APIs to not employ or support it. As far as the URL grammar is concerned, "input[]" is just another parameter name, unrelated to "input" and having no special significance, and any parameter name may be repeated. – Semicolon Jun 19 '19 at 18:55

2 Answers2

3

Ran into a similar issue, there's a helpful post here Ruby Hash with duplicate keys? but briefly

params = {}.compare_by_identity
params['input'] = "webpage/url:http://www.example.com"
params['input'.dup] = "keywords:some+keywords"

then

params.to_query

returns

"input=keywords%3Asome%2Bkeywords&input=webpage%2Furl%3Ahttp%3A%2F%2Fwww.example.com"
Community
  • 1
  • 1
Leo
  • 1,539
  • 17
  • 15
1

Some characters in a url have special importance to the processing of the url: they are reserved, like keywords in a programming language. See Which characters make a URL invalid?

If you try to use these as the name or value of a parameter, it will break the uri and you'll get hard to predict results like you're seeing.

The answer is to URI escape the string, which will replace special characters with their encoded version. Rails will automatically unescape them when it gets the the request, so you don't need to worry about it.

You can escape them manually, but the best way, if you have them as a hash already, is to call .to_param on the hash.

params = { :input => ["webpage/url:http://www.example.com", "keywords:some+keywords"] }
=> {:input=>["webpage/url:http://www.example.com", "keywords:some+keywords"]}
params.to_param
=> "input%5B%5D=webpage%2Furl%3Ahttp%3A%2F%2Fwww.example.com&input%5B%5D=keywords%3Asome%2Bkeywords"
Community
  • 1
  • 1
Max Williams
  • 32,435
  • 31
  • 130
  • 197