Need alternative for eval - ruby-on-rails

I have a string
string = '{"a" => [{"b" => 2}]}'
eval(string)
# => {"a" => [{"b" => 2}]}
I need alternative for this to have output like {"a" => [{"b" => 2}]}

When storing data in strings that will be parsed programmatically, it's best to format those strings using a standardized data-interchange format, such as JSON. Your string, formatted into JSON, would look like this:
{"a": [{"b": 2}]}
If you have any control over how the data is saved in excel, you should make sure it's saved in JSON format like this. If, for some reason, you're not allowed to modify the format of the data in excel, your next best option is to convert it to JSON before parsing it.
Fortunately for you, the data is already very similar to JSON. The only difference is that JSON uses : instead of =>, so you can do this:
require "json"
string = '{"a" => [{"b" => 2}]}'.gsub("=>", ":")
data = JSON.parse string
p data # => {"a" => [{"b" => 2}]}

Related

Remove slash from string in ruby on rails

I need to remove "\" from below string
{\"MACAddress\":\"74:5E:78\",\"DeviceName\":\"Connected_Device\"}
Response should be
{"MACAddress":"74:5E:78","DeviceName":"Connected_Device"}
I need to check if string includes "\n",i need to add validation to remove "\"
Can you please help how to handle this in rails?
Currently i am using httpparty below code
reqType = params['reqType']
payLoadData = params['payLoadData']
p "PAYLOAD DATA-------------- #{payLoadData}"
if reqType == "post"
start = Time.now
url=params['url']
body_param= device
p "payLoadData-------------- #{body_param}"
response = HTTParty.post(url,
:body => body_param,
:headers => {'Content-Type' => 'application/json','User-Agent'=> 'Auto',"Authorization" => 'Basic=='})
result_hash["response"].push({"body": response.body.to_s, "response_time": response_time.to_s})
result_hash["status"].push(response.code)
JSON.parse("{\"MACAddress\":\"74:5E:78\",\"DeviceName\":\"Connected_Device\"}")
It should do the trick
The response that you get from your Ajax call is a hash in JSON format.
Just use a JSON parser to translate the JSON string into a Ruby hash:
require 'json'
pay_load = params['payLoadData']
device = JSON.parse(pay_load)
device['MACAddress']
#=> "74:5E:78"
device['DeviceName']
#=> "Connected_Device"
When you just want to output the hash a simple puts device or a <%= device %> (depending on your context) should work. Because in both cases to_s is called on the hash internally.

How to convert a hash to JSON without the converted string being full of backslashes

I am converting a hash to JSON using to_json, but the converted string is full of backslashes. If I use puts, it shows the correct string but if I pass in a HTTP::NET request.body, the string is full of backslashes.
data = {"a" => "b", "c" => "d", "e" => "f"}
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.path, {'Content-Type' =>'application/json',
'Authorization' => "xyz")
req.body = data.to_json
res = http.request(req)
req.body is sending:
"{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"}"
My request is failing because of this.
I need to send data as
"{"a" => "b", "c" => "d", "e" => "f"}"
in the request body.
It seems like you are confused about the actual content of the string. The backslashes are part of the string representation, and are not actually in the string.
Take for example '"' a single character ". When you enter this into irb the output will be:
s = '"'
#=> "\""
From the result "\"" the starting " and ending " mark the begin and ending of the string while \" is an escaped double quote, and represents a single ". The reason this double quote is escaped is because you want Ruby to interpret it as an " character, not as the end of the string.
You can view the actual contents of the string without escape characters by printing it to the console.
puts s
# "
#=> nil
Here you can see that there is no backslash in the contents of the string.
The same applies for your to_json call, which returns a string:
data = {"a" => "b", "c" => "d", "e" => "f"}
json = data.to_json
#=> "{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"}"
puts json
# {"a":"b","c":"d","e":"f"}
#=> nil
Like you can see there are no backslashes in the contents of the string, only in the string representation.
You can handle this problem with two solutions: Either you can parse the JSON where you want to use it, or you can also send parsed JSON from Ruby code.
req.body = JSON.parse(data.to_json)
It will return the result like:
{"a"=>"b", "c"=>"d", "e"=>"f"}
It depends on you where you want to parse your data. If you want to parse on the frontend just use jQuery's JSON parse function.
Try as_json which might be more appropriate given what you're attempting. This is a good explanation of which to use and when. as_json will produce unescaped json.
Totally understand that the slash is an accepted escape on the string, but there are applications that do not accept it IE Amazon Connect.
req.body = JSON.parse(data.to_json)
Works perfectly.

How do I pass this param properly?

I want to make an API request with a text param, with information I currently have in params[:brand][:tag_list] which seems to be saved as a single comma-delimited string. What's the correct way to make the API request?
Controller code:
current_user.tag(#brand, :with => params[:brand][:tag_list], :on => :tags)
url = "http://www.viralheat.com/api/sentiment/review.json"
#sentiment_response = url.to_uri.get(
:api_key => 'MY_KEY',
:text => :tag_list ).deserialize #This is what I'm currently using and is wrong
Response codes from log:
<- (GET 49996946161 2204098100) http://www.viralheat.com:80/api/sentiment/review.json?api_key=MY_KEY&text=tag_list
-> (GET 49996946161 2204098100) 200 OK (62 bytes 3.09s)
Looking up the docs for viralheat, it looks like their api accepts exactly two parameters: api_key, and text. Assuming params[:brand][:tag_list] a comma-delimited string, you can form your request like so:
current_user.tag(#brand, :with => params[:brand][:tag_list], :on => :tags)
url = "http://www.viralheat.com/api/sentiment/review.json"
#sentiment_response = url.to_uri.get(
:api_key => 'MY_KEY',
:text => params[:brand][:tag_list].split(',').join('&') ).deserialize
This should create the url:
http://www.viralheat.com/api/sentiment/review.json?api_key=MY_KEY&text=cat%26dog%26​mouse
params[:brand][:tag_list].split(',') breaks your string into an array, and join('&') turns it back into a string, but this time delimited by ampersands (which seems to be what you want, based on what you said in a comment on your original post). Your uri.get method should escape the ampersands in the uri, which is why you see the %26s in the final url. This is correct.

Rails: Opposite of Hash#to_param

If I convert a hash to a query string, how can I convert it back again?
{:filters => {:colour => ['Red', 'Blue'], :size => 'Medium'}}.to_param
=> "filters[colour][]=Red&filters[colour][]=Blue&filters[size]=Medium"
Rails appears to do this automatically when it populates the params hash, but is it possible to call this method directly?
Thanks.
You're looking for Rack::Utils.parse_nested_query(query), which will convert it back into a Hash. You can get it by using this line:
require 'rack/utils'
query_string = "filters[colour][]=Red&filters[colour][]=Blue&filters[size]=Medium"
CGI::parse(query_string)

Accessing data from httparty response

Using httparty I can get the following response:
puts Representative.find_by_zip(46544).inspect
-->
{"results"=>[{"name"=>"Joe Donnelly", "district"=>"2", "office"=>"1218 Longworth", "phone"=>"(202) 225-3915", "link"=>"http://donnelly.house.gov/", "state"=>"IN"}]
source of the example: http://railstips.org/blog/archives/2008/07/29/it-s-an-httparty-and-everyone-is-invited/
but I fail to access the data, for example:
Representative.find_by_zip(46544).inspect["name"] returns nil
How can I access individual elements of this response?
Object#inspect returns a string, not a hash. You want this:
Representative.find_by_zip(46544)['results'][0]['name']
This is what's going on: Representative#find_by_zip returns a Hash with just one index: 'results'. The item at 'results' is an array, which in this case only contains one element, so we use [0] to get the first (and only) element. That element is itself a hash that has the 'name' key, which points to the name of the first (and only) representative returned.
When you have complex hashes and arrays it's sometimes useful to format it in a more readable way to figure out how to get at the data you want:
{ "results" => [
{ "name" => "Joe Donnelly",
"district" => "2",
"office => "1218 Longworth",
"phone" => "(202) 225-3915",
"link" => "http://donnelly.house.gov/",
"state" => "IN"
}
]
}
That should make it more clear what's inside what here.
To Access the individual elements, You can use:-
If the response is JSON:-
You can use:-
response.parsed_response["key"]
If your response is a string then, you can use:-
data = JSON.parse(resp.body)
The response type depends, on the content type you are setting while requesting the data:-
'Content-Type' => 'application/json'
If you don't set the content type it returns response as string.

Resources