How to parse request data with ruby - ruby

I'm using sendgrid's event api which sends a codeblock like this to a postback url of my choice:
Array
(
[email] => fgdfg#gmail.com
[timestamp] => 1323698899
[smtp-id] => <4ee60acf8e3d1_55dd862cf147044#mbjoppa.mail>
[response] => 250 2.0.0 OK 1323698899 o30s15072o427yhl.103
[event] => delivered
)
They don't have XML or JSON and I need to extract the email and event parts of this block.
Any idea how I do this with rails? Basically this block is sent to a postback URL of my choice but I'm not sure how to use it from there.

I never used sendgrid but after a quick look it seems like they are just sending you a standard post request with parameters so you best bet is to define a simple action like the following and see what you get:
def sendgrid_event
Rails.logger.info(params)
# chances are that this will contains what you are looking for:
# params['email']
# params['event']
end

Related

Watir message: Instead of passing arguments into #wait_until_present method, use keywords

I use watir with firefox to grab a webpage after filling a form. Here a short part of my code:
browser.button(:type => 'submit').click
sleep 10
browser.element(:id => 'footer').wait_until_present(timeout=30)
html = browser.html
This message occur:
Instead of passing arguments into #wait_until_present method, use Keywords
What does that mean? How can i solve this?
Thanks for help.
The answer is on the new Watir 6.0 FAQ:
http://watir.github.io/watir-6-faq/#G
In your case, change from timeout=30 to timeout: 30 and you won't see the warning message.
The API of watir says #wait_until_present(timeout = nil) ⇒ Object
The timeout = nil part is an optional parameter, if you want a timeout you just need to pass a number to the method.
browser.element(:id => 'footer').wait_until_present(30)

Sending a POST request from a GET-structured URL

I have GET-type URLs with the parameters at the end of the URL string. I need to restructure them so that the stuff before the ? becomes the endpoint and the stuff after gets sent out as parameters in a correctly-formatted POST request payload.
For example:
http://ecample.com?test=true&message=hello
needs to be sent out as a POST request to the URL http://example.com with a request payload of:
{"test":true,"message":"hello"}
Any ideas or quick tricks to get this so I can get the POST response?
Meditate on this:
require 'uri'
scheme, userinfo, host, port, registry, path, opaque, query, fragment = URI.split('http://example.com?test=true&message=hello')
scheme # => "http"
userinfo # => nil
host # => "example.com"
port # => nil
registry # => nil
path # => ""
opaque # => nil
query # => "test=true&message=hello"
fragment # => nil
uri = URI.parse('http://example.com?test=true&message=hello')
server = '%s://%s' % [uri.scheme, uri.host] # => "http://example.com"
parameters = Hash[URI.decode_www_form(uri.query)] # => {"test"=>"true", "message"=>"hello"}
At this point you can use whatever you want to connect to the server and send the parameters using GET, POST or any of the other request types.
URI is built into Ruby and has all the methods necessary to take apart URLs correctly and rebuild them.
When learning a computer language, it's mandatory to read through all the libraries and become familiar with their offerings. I do it many times, not to know exactly where a particular method is and its parameters, but to remember that it exists somewhere and then I can search and find it. Any modern language that can talk to web services will have such functionality available to it; It's your job to read the documentation and become familiar with it.

how do I parse out this URL-encoded string with a JSON array using Ruby?

When I use a webhook with Mandrill and post to my Iron Worker, I get the following Raw (this is from RequestBin, as well) -- I didn't include the whole payload, just an example:
puts payload =>
mandrill_events=%5B%7B%22event%22%3A%22inbound%22%2C%22msg%22%3A%7B%22dkim%22%3A%7B%22signed%22%3Atrue%2C%22valid%22%3Atrue%7D%2C%22email%22%3A%22kaya%40hellokaya.com%22%2C%22from_email%22%3A%22example.sender%40mandrillapp.com%22%2C%22headers%22%3A%7B%22Content-Type%22%3A%22multipart%5C%2Falternative%3B+boundary%3D%5C%22_av-7r7zDhHxVEAo2yMWasfuFw%5C%22%22%2C%22Date%22%3A%22Fri%2C+10+May+2013+19%3A28%3A20+%2B0000%22%2C%22Dkim-Signature%22%3A%5B%22v%3D1%3B+a%3Drsa-
I tried to extract the value of the parameter mandrill_events using:
puts params = CGI::parse(#payload) =>
{"mandrill_events"=>["[{\"event\":\"inbound\",\"msg\":{\"dkim\":{\"signed\":true,\"valid\":true},\"email\":\"kaya#hellokaya.com\",\"from_email\":\"example.sender#mandrillapp.com\",\"headers\":{\"Content-Type\":\"multipart\\/alternative; boundary=\\\"_av-7r7zDhHxVEAo2yMWasfuFw\\\"\",\"Date\":\"Fri, 10 May 2013 19:28:20 +0000\",\"Dkim-Signature\":[\"v=1; a=rsa-sha1; c=relaxed\\/relaxed; s=mandrill; d=mail115.us4.mandrillapp.com; h=From:Sender:Subject:List-Unsubscribe:To:Message-Id:Date:MIME-Version:Content-Type; i=example.sender#mail115.us4.mandrillapp.com;
Then I am stuck. I want to extract the email value in the JSON.array.
I thought to try the following;
puts json_params = JSON.parse(params)
But I am now feeling there must be a better way....
How can I extract the elements from the JSON array in this URL-encoded string?

Sending raw XML using Savon 2

I'm trying to use Savon to send requests to a webservice. The service I'm consuming requires nested namespaces, and I haven't figured out yet how to provide them on a request.
I've tried to craft the request by hand (with nokogiri, actually) and send the resulting xml:
client.call(:some_op, :message=>{:"op"=>"<elem/>"})
But savon escapes the string and sends <elem/>
How can I send raw xml without escaping?
The call should look like this:
client.call(:some_op, xml: "<elem />")
Or if you just want to set one or multiple namespaces then create a client as follows (without WSDL):
client = Savon.client(
:endpoint => 'http://www.example.com',
:namespace => 'urn:core.example.com',
:namespaces => { 'ns1' => 'http://v1.example.com',
'ns2' => 'http://v2.example.com' },
:log => true,
:log_level => :debug,
:pretty_print_xml => true
)
The namespaces are a Hash parameter.
It looks like Savon internally uses the Gyoku Gem to convert ruby hashes to XML, and Gyoku will not escape hash keys ending with exclamation marks according to the documentation: https://github.com/savonrb/gyoku#special-characters
So this code works to get raw XML into the request while still using Savon to generate the envelope xml:
client.call(:some_op, :message=>{:"op!"=>"<elem/>"})

Ruby Sinatra and JSON objects from toodledo API 2.0

I have a small problem with receiving JSON objects. I'm using Ruby 1.9.3 and my goal is to receive my tasks from an API via RestClient and print them more or less pretty onto the page.
I created a route /test:
get '/test' do
json_ip_url = "http://api.toodledo.com/2/tasks/get.php?key=198196ae24792467eec09ac2191*****;modafter=1234567890;fields=folder,star,priority"
ip_details = RestClient.get(json_ip_url)
test = JSON.pretty_generate(ip_details) # => throws exception
end
The JSON#pretty_generate line throws an error, "only generation of JSON objects or arrays allowed". What am I doing wrong here?
Update:
I'am now able to output via pretty_generate, but what do I have to do, to get the elements of it. Here is the JSON Data, it seems to me its an Array with Objects inside of it?
[{"num":"18","total":"18"},{"id":"11980343","title":"Add some items to your todo list","modified":1391670256,"completed":0,"folder":"0","star":"0"},{"id":"11980345","title":"Visit the Settings section and configure your account","modified":1391670256,"completed":0,"folder":"0","star":"0"},{"id":"11980347","title":"Watch our tutorial videos in the Help section","modified":1391670256,"completed":0,"folder":"0","star":"1"},{"id":"12607789","title":"test","modified":1392285802,"completed":0,"folder":"0","star":"0"},{"id":"12636039","title":"My Task","modified":1392308705,"completed":0,"folder":"0","star":"0"},{"id":"12636041","title":"Another","modified":1392308705,"completed":0,"folder":"0","star":"1"},{"id":"12636143","title":"My Task","modified":1392308789,"completed":0,"folder":"0","star":"0"},{"id":"12636145","title":"Another","modified":1392308789,"completed":0,"folder":"0","star":"1"},{"id":"12636449","title":"My Task","modified":1392308950,"completed":0,"folder":"0","star":"0"},{"id":"12636451","title":"Another","modified":1392308950,"completed":0,"folder":"0","star":"1"},{"id":"12636621","title":"My Task","modified":1392309061,"completed":0,"folder":"0","star":"0"},{"id":"12636623","title":"Another","modified":1392309061,"completed":0,"folder":"0","star":"1"},{"id":"12636665","title":"My Task","modified":1392309085,"completed":0,"folder":"0","star":"0"},{"id":"12636667","title":"Another","modified":1392309085,"completed":0,"folder":"0","star":"1"},{"id":"12636733","title":"My Task","modified":1392309137,"completed":0,"folder":"0","star":"0"},{"id":"12636735","title":"Another","modified":1392309137,"completed":0,"folder":"0","star":"1"},{"id":"12637135","title":"My Task","modified":1392309501,"completed":0,"folder":"0","star":"0"},{"id":"12637137","title":"Another","modified":1392309501,"completed":0,"folder":"0","star":"1"}]
The Code I used for pretty_generate:
get '/save' do
jdata = params[:data]
response = RestClient.get 'http://api.toodledo.com/2/tasks/get.php?key=da21e24e2a00ba9d45008974aed00***;modafter=1234567890;fields=folder,star,priority', {:accept => :json}
test = JSON.parse(response)
test.to_json
output = JSON.pretty_generate(test)
puts output
RestClient#get returns the raw response as a string (and not a hash or array) when called without a block, so ip_details isn't a structure that JSON#pretty_generate knows how to handle. You need to use JSON#parse to turn the response into a hash or array first.

Resources