22

I have a callback url string params[:callback] and I need to append a query string "&result=true" and redirect the user. The better way I found of doing this is using addressable but I think the code is too big for task like this especially when we are talking about ruby:

callback = Addressable::URI.parse(params[:callback])
query = callback.query_values
query[:result] = 'true'
callback.query_values = query

redirect_to callback.to_s

Is there a more elegant way of getting the same result as this snippet?

0

7 Answers 7

15

I wan't to bring update to this topic, because any of the solutions didn't work me.

The reason being, that it seems that callback.query_values returns Nil if the actual url doesn't have existing query values.

Therefore if you have urls such as: http://www.foo.com and http://www.foo.com?bar=1 you should use the following code:

url = "http://www.foo.com" # or params[:callback] obviously. :)

callback = Addressable::URI.parse(url)
callback.query_values = (callback.query_values || {}).merge({
  result: true
})

redirect_to callback.to_s

Cheers.

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

1 Comment

I just want to add that If the param may already exist make sure that "result" is a string, not a symbol :result so you don't get a double param like "foo.com?result=true&result=true" or "foo.com?result=true&result=false". Also if true is a boolean result: true and not a string result: "true" this can raise an ArgumentError (comparison of Array with Array failed)
9
  • if you don't need any URL validations you can do this (looks a little bit dirty):
    
    url = params[:callback]
    redirect_to url + (url.include?('?') ? '&' : '?') + 'result=true'
    
  • otherwise you have to use either some external library (like Addressable) or URI module from standard library

1 Comment

yeah, it looks dirty. Looking at my code using Addressable is there anyway this code could be shorter ?
3
callback.query_values = callback.query_values.merge({"result" => "true"})

1 Comment

Mauna's answer below is better because callback.query_values can return nil, which does not respond to merge
0

I think you're pretty close to optimal. you could crush out a line or two, but it doesn't really gain you anything.

callback = Addressable::URI.parse(params[:callback])
callback.query_values = callback.query_values.merge {:results => 'true' }
redirect_to callback.to_s

If the callback is always inside your application, you might have some other options with varying degrees of coolness, but you didn't specify if that was the case or not.

Comments

0

years later, I find a better solution of this problem.

Get the value from the super first, then do any tweaks we need using Addressable

def url_for(options={})
  val = super

  if params[:locale].present?
    parsed = Addressable::URI.parse(val)
    query_array = parsed.query_values(Array) || []
    query_array << ['locale', params[:locale]]
    parsed.query_values = query_array
    val = parsed.to_s
  end

  val
end

Comments

-1

Let me offer this one modestly. I suggest using only strings for query parameters keys and values (like Arye noted) . Also, NilClass instances have a to_h method, which allows to remove some brackets:

callback = Addressable::URI.parse(params[:callback])

callback.query_values = callback.query_values.to_h.merge("result" => "true")

redirect_to callback.to_s

Comments

-3

You can try with merge

request.parameters.merge({:result => true})

this will add your parameter to the ones already defined.

1 Comment

OP has the URL in a variable. It's not the current request URL

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.