Multiple JSON objects in the stream - ruby-on-rails

I am trying to execute two helper functions of in a view call the second with the return of the first. I know the following functions properly returns the desired hash:
%p = helper_method0 params[:some_string] #does a request on a third party site which responds with json data wich is then parsed by yajl and the hash is returned to view
However when I call the following:
- hash = helper_method0 params[:some_string] #does a request on a third party site which responds with json data wich is then parsed by yajl and the hash is returned to view
%p= helper_method1 hash #Literally is just returning the input parameter
I receive the following error message
Found multiple JSON objects in the stream but no block or the on_parse_complete callback was assigned to handle them.
How do I call a method with an input parameter as the return of another method from the view?

What you are doing is perfectly correct :)
And you could also do:
(if you want to save bytes and variables)
%p= helper_method1( helper_method0 params[:some_string] )
But anyway...
This error sounds like a problem in the json parser... are you using Yajl?
I have seen this issue when using Yajl like this:
parser = Yajl::Parser.new
hash = parser.parse(some_string)
What worked for me was to use the Yajl class method like this:
Yajl::Parser.parse(some_string.strip)
I hope this helps :)

Related

Accessesing saved JSON response in column

Okay, I am using HTTParty to save a JSON response in my show.subsources column. Subsources is a text type column.
For example, one of my subsources: column currently has the data saved as so:
[{"source"=>"hulu_free", "display_name"=>"Hulu", "id"=>6001348,"link"=>"http://www.hulu.com/watch/843378"}]
To me, this looks like a hash within an array. How do I access each hash within the array, so that I can correctly display the "source" name in my views?
What I have tried is:
<% showdata = show.subsources %>
<%= showdata[0]['sources'] %>
I am expecting that to display 'hulu_free', but instead it will not show anything in my views. Am I not using the right syntax to access that hash? Or am I not saving the JSON correctly in order for me to access the hash data? Do I need to parse the data first? I have spent way too long trying to figure this out.
In your case you can easily get JSON representation and parse it to Hash.
text = text = %q{[{"source"=>"hulu_free", "display_name"=>"Hulu", "id"=>6001348,"link"=>"http://www.hulu.com/watch/843378"}]}
text.gsub!('=>',':')
JSON.parse(text) # => returns hash
I'm not sure how internals work in your program, but probably you should consider to put JSON like text into this field.

Parsing twitter json response

I've made a twitter api request (GET trends/place API) and the result is just like this:
[{"trends":[{"name":"#BabyIsStaying","url":"http:\/\/twitter.com\/search?q=%23BabyIsStaying","promoted_content":null,"query":"%23BabyIsStaying","events":null},{"name":"#AkTakipBa\u015fl\u0131yor","url":"http:\/\/twitter.com\/search?q=%23AkTakipBa%C5%9Fl%C4%B1yor","promoted_content":null,"query":"%23AkTakipBa%C5%9Fl%C4%B1yor","events":null},{"name":"#\u00c7apulcuTakip","url":"http:\/\/twitter.com\/search?q=%23%C3%87apulcuTakip","promoted_content":null,"query":"%23%C3%87apulcuTakip","events":null},{"name":"#SadeceKar\u015f\u0131l\u0131kl\u0131Takiple\u015fme","url":"http:\/\/twitter.com\/search?q=%23SadeceKar%C5%9F%C4%B1l%C4%B1kl%C4%B1Takiple%C5%9Fme","promoted_content":null,"query":"%23SadeceKar%C5%9F%C4%B1l%C4%B1kl%C4%B1Takiple%C5%9Fme","events":null},{"name":"#soysuzek\u015fis\u00f6zl\u00fck","url":"http:\/\/twitter.com\/search?q=%23soysuzek%C5%9Fis%C3%B6zl%C3%BCk","promoted_content":null,"query":"%23soysuzek%C5%9Fis%C3%B6zl%C3%BCk","events":null},{"name":"B\u00fcy\u00fck FENERBAH\u00c7E Taraftarlar\u0131Takiple\u015fiyor","url":"http:\/\/twitter.com\/search?q=%22B%C3%BCy%C3%BCk+FENERBAH%C3%87E+Taraftarlar%C4%B1Takiple%C5%9Fiyor%22","promoted_content":null,"query":"%22B%C3%BCy%C3%BCk+FENERBAH%C3%87E+Taraftarlar%C4%B1Takiple%C5%9Fiyor%22","events":null},{"name":"Sar\u0131K\u0131rm\u0131z\u0131Aile UnfollowsuzTakiple\u015fiyor","url":"http:\/\/twitter.com\/search?q=%22Sar%C4%B1K%C4%B1rm%C4%B1z%C4%B1Aile+UnfollowsuzTakiple%C5%9Fiyor%22","promoted_content":null,"query":"%22Sar%C4%B1K%C4%B1rm%C4%B1z%C4%B1Aile+UnfollowsuzTakiple%C5%9Fiyor%22","events":null},{"name":"D\u00fcnyadaTeksinSen GALATASARAY\u0131m","url":"http:\/\/twitter.com\/search?q=%22D%C3%BCnyadaTeksinSen+GALATASARAY%C4%B1m%22","promoted_content":null,"query":"%22D%C3%BCnyadaTeksinSen+GALATASARAY%C4%B1m%22","events":null},{"name":"D\u00fcnyan\u0131n TekHarikas\u0131s\u0131n FENERBAH\u00c7EM","url":"http:\/\/twitter.com\/search?q=%22D%C3%BCnyan%C4%B1n+TekHarikas%C4%B1s%C4%B1n+FENERBAH%C3%87EM%22","promoted_content":null,"query":"%22D%C3%BCnyan%C4%B1n+TekHarikas%C4%B1s%C4%B1n+FENERBAH%C3%87EM%22","events":null},{"name":"MustafaKemalin\u0130zindeyiz \u00c7\u00fcnk\u00fcFenerbah\u00e7eliyiz","url":"http:\/\/twitter.com\/search?q=%22MustafaKemalin%C4%B0zindeyiz+%C3%87%C3%BCnk%C3%BCFenerbah%C3%A7eliyiz%22","promoted_content":null,"query":"%22MustafaKemalin%C4%B0zindeyiz+%C3%87%C3%BCnk%C3%BCFenerbah%C3%A7eliyiz%22","events":null}],"as_of":"2013-07-20T10:51:45Z","created_at":"2013-07-20T10:45:24Z","locations":[{"name":"Turkey","woeid":23424969}]}]
My question is how to turn this array string into html. No proper php experience at all.
The response you are getting is JSON.
You used to be able to get response in XML, RSS and more, but now the only response type you will receive is JSON.
PHP has multiple methods for dealing with JSON. To encode data, you would use json_encode(). However, you want to decode it, so you want to be doing the following:
var_dump(json_decode($yourData));
This will dump the data to the browser so you can see what you have to work with.
You can iterate around this data using a foreach() loop.
Remember, assuming you json_decode() your results into $yourData:
To access array properties, use: $yourData['propertyName']
To access object properties, use: $yourData->propertyName
you can feed that into json_decode() function
you will get an array that you can manage as you want.

Passing array of parameters through get in rails

How do I pass array of parameters through Get method in rails? Currently my URL loocs like this:
http://localhost:3000/jobs/1017/editing_job_suites/1017/editing_member_jobs/new?ids[]=1025&ids[]=1027
How can I pass the array with Get method but avoid ?ids[]=1025&ids[]=1027 part.
Request is being sent with javascript window.open method. Is there any workaround to send not ajax Post request.
You should stick to using a GET request if you are not changing the state of anything, and all you want to to access a read only value.
To send an array of ids to rails in a GET request simply name your variable with square brackets at the end.
//angular snippet
$http.(method:'GET',
...
params: {'channel_id':2, 'product_ids[]': productIds}
//where productIds is an array of integers
...
)
Do not concatenate your ids as a comma separated list, just pass them individually redundantly. So in the url it would look something like this:
?channel_id=2&product_ids[]=6900&product_ids[]=6901
url encoded it will actually be more like this:
?channel_id=2&product_ids%5B%5D=6900&product_ids%5B%5D=6901
Rails will separate this back out for you.
Parameters: {"channel_id"=>"2", "product_ids"=>["6900", "6901"]}
No, GET can only put variables on the url itself. If you want the URL to be shorter, you have to POST. That's a limitation feature of HTTP, not Rails.
I recently wanted to do this and found a workaround that is a little less complex, and so has some complexity limitations but may also be easier to implement. Can't speak to security, etc.
If you pass your array values as a string with a delimiter, e.g.
http://example.com/controller?job_ids=2342,2354,25245
Then you can take the result and parse it back to what you want:
job_ids = params[:job_ids].split(',')
Then do whatever:
job_ids.each do |job_id|
job = Job.find(job_id.to_i)
end
etc
#Homan answer is valid for using an external client (e.g curl or angular). Inside Rails test cases though, you should not use []. Here's an example:
get get_test_cases_url(**path_params), params: {case_ids: ["NON-9450", "NON-12345", "NON-9361"]}
This is using new format where get_test_cases is name of route and you pass to the method all params needed to construct the URL path. Query params are a separate hash.
FYI if I use [] like case_ids[], then instead of ["NON-9450", "NON-12345", "NON-9361"] I'm getting it parsed to [["NON-9450"], ["NON-12345"], ["NON-9361"]]

Assembling SOAP Header manually with Savon

I've been dealing with a "soap message header incorrect" error message when submiting a SOAP request using Savon.
I copy/pasted the exact same xml generated by Savon into SOAPUI and I don't get that error and I get the expected response.
So, since I'm tired of trying different things, I want to assemble my own header without Savon help on that.
What I want to do is something like:
soap.header = "<wbs:Session><wbs:SessionId></wbs:SessionId><wbs:SequenceNumber></wbs:SequenceNumber></wbs:Session>"
However I get this error from Savon:
can't convert Symbol into String
Why?
Thank you in advance.
Its likely caused by the fact you havent set any values.
I was getting this error when I had a hash containing just one custom object on return, as it was trying to access parts of the hash that had automatically been removed. (it removed unnesscary layer of hash for me :#)
I believe the header will only accept a Hash - from the savon.rb page:
Besides the body element, SOAP requests can also contain a header with
additional information. Savon sees this header as just another Hash following
the same conventions as the SOAP body Hash.
soap.header = { "SecretKey" => "secret" }

Parsing JSON Payload in Rails When Using Custom MIME Type

A Rails application with a RESTful interface needs to accept POST data using a custom MIME type based on 'application/json'. Let's call that MIME type 'application/vnd.com.example.Foo+json'.
Registering the custom MIME type in Rails using Mime::Type.register works fine in that the application recognizes the MIME type given in the "Accept:" header and renders a JSON view through respond_to.
The problem is with controller methods such as update and create that need to convert custom JSON formatted data into a params hash. If I set the "Content Type:" header to application/json, the data gets parsed into the params hash.
But if I set the "Content Type:" header to 'applcation/vnd.com.example.Foo+json', then the payload does not get parsed.
So it seems like MIME::Type.register is used for driving the respond_to block, but not in deciding how to parse payloads for create and update methods.
Any ideas?
For those who may be interested, I found the answer to my own question.
Use something like this in mime_types.rb (or possibly elsewhere in your your initialization sequence):
ActionController::Base.param_parsers[Mime::Type.lookup('application/vnd.com.example.foo+json')]=lambda do |body|
JSON.parse body
end
One catch: don't use capitalization in the MIME type above (i.e., 'application/vnd.com.example.Foo+json'). Rails converts the MIME type into all lower case, so no match will be found it it's set to upper case.
In Rails 5 do:
ActionDispatch::Request.parameter_parsers[Mime::Type.lookup('application/vnd.api+json').symbol] = lambda do |body|
JSON.parse(body)
end
In Rails 3 do:
ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime::Type.lookup('application/vnd.com.example.foo+json')]=lambda do |body|
JSON.parse(body)
end
Here's what I learned working with this in Rails 5:
Rich's information was a great starting point and, like him, I added my code in an initializer (in config/initializers/mime_types.rb).
In my scenario, when working with a custom content type that can be parsed as regular json, it's simple to add another synonym to the json mime type like this:
json_mime_type_synonyms = %w[
text/x-json
application/jsonrequest
application/foobar+json
]
Mime::Type.register('application/json', :json, json_mime_type_synonyms)
If you take that approach, be sure to include the other synonyms (they're from the default json mime type) to ensure they continue to work properly.
Alternatively, if you need custom parsing logic or prefer separate mime types, here is how to both register the mime type and its associated parameter parser:
Mime::Type.register('application/foobar+json', :foobar_json)
ActionDispatch::Request.parameter_parsers[:foobar_json] = -> (body) {
JSON.parse(body)
}

Resources