Reputation: 4381
I have the following code that generates a hash used for testing the authentication of a internal Restful API.
The problem is the generated hash is returning escaped values.
The json_headers
method should return something like this:
{"Authorization"=>"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==", "Accept"=>"application/json"}
But is returning:
{\"Authorization\"=>\"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==\\n\", \"Accept\"=>\"application/json\"}
Does anyone know an easy way to return raw key/values from a Ruby hash?
Here is the code:
module ERP
class CustomersMock
def json_headers
authorization_hash.merge("Accept"=>"application/json")
end
def authorization_hash
{"Authorization" => "Basic #{base64_user_pass}"}
end
def user_pass
# user:password
[ ERP_CONF['user'], ERP_CONF['password'] ].join(':')
end
def base64_user_pass
Base64.encode64(user_pass)
end
def add(customer)
customers << customer
end
def customers
[]
end
def run
ActiveResource::HttpMock.respond_to do |mock|
customers.each do |customer|
mock.get "/customers/#{customer.id}.json", json_headers, customer.to_json
end
end
end
end
end
For some reason, if I hard-code the headers hash in place, they work, but if I call the json_headers
method, the respond_to
block converts them to a string and escapes the values.
Here is the rspec failure:
Could not find a response recorded for <GET: /api/customers/1011.json [{"Authorization"=>"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==", "Accept"=>"application/json"}] ()> - Responses recorded are: ["<GET: /api/customers/1011.json [{\"Authorization\"=>\"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==\\n\", \"Accept\"=>\"application/json\"}] ()>"]
Upvotes: 3
Views: 4390
Reputation: 4381
This was not a escaping problem. I thought it was based on the rspec failing test output:
Could not find a response recorded for
<GET: /api/customers/1011.json [{"Authorization"=>"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==", "Accept"=>"application/json"}] ()>
- Responses recorded are: [
"<GET: /api/customers/1011.json [{\"Authorization\"=>\"Basic ZnBfZXJwOllrdGh4aHRSZTZWM1d1d09oeVlmcW0xTg==\\n\", \"Accept\"=>\"application/json\"}] ()>"
]
It looks like the only difference is the headers hash is escaped in one and not in the other.
However, it is not escaping the line ending at the end of the "Authorization" value, so the fix is to strip the value:
def base64_user_pass
Base64.encode64(user_pass).strip
end
Upvotes: 0
Reputation: 54684
Escaped quotes are a bit confusing at first. I guess you were testing this from a REPL such as IRB or Pry. Your method actually contains normal double quotes – they are only escaped for output because double quotes are already used to denote the beginning and end of a string. That means that when you actually want to store the double quote character "
in a string, you need to type "\""
because if you were typing """
you would actually end the string with the second "
. You can see what a string "really" contains by actually printing it with puts
. Let me demonstrate this with an example:
require 'json'
h = {a: 123, b: 456}
h.to_json
#=> "{\"a\":123,\"b\":456}" # note the escaped double quotes
puts h.to_json
# {"a":123,"b":456} # when printed, quotes are no longer escaped
double_quote_1 = '"' # another way to store " in a string
double_quote_2 = "\""
double_quote_1 == double_quote_2 # both have the same contents, a single "
#=> true
json1 = '{"a":123,"b":456}' # less confusing way of writing the json from above
json2 = "{\"a\":123,\"b\":456}"
json1 == json2
#=> true
Upvotes: 3