Wednesday 16 October 2013

Intro Who am I and Make Google API Calls in Ruby 2.0.0

This month has been a time of bizarre growth so, it is time to start writing.
Forgive me for the ramblings. This blog post is meant to share in some ways, but mostly, to force me to start blogging. I promise the next one will show more organization and full working bits of code. This is my 'get yourself out there' article. You know, like the first time you were ever interviewed and the interviewer asks you a question you don't know so you look around for someone that does know the answer - we've all seen the kids do it.
First a thanks to a huge community on the Internet, developing with limited feedback and no direction is incredibly easy. Second, I'm not quite all alone. However, going from working with a huge team to a smaller one at Castle Rock and now in a team of four has been a great experience. Don't start here, really, go for the larger team first!
This month has been about programming, marketing, and wonderfully crazy friends.
Programming - Why would a CSO with no formal programming background want to program?  Reason: Marketing.

Marketing - Makes or breaks a business, we have to do it, and, to be honest, that's what I've been doing since starting at GEE. It just looks like development, when the reality is webpages, demo products, and inventive ways to market are all marketing. Oh - and sorry to say it world, but so is blogging. Does that mean I won't contribute to the world? Absolutely not, marketing is awfully soul destructive if it doesn't build the community around you.

Wonderfully Crazy Friends - if you don't have some, get some. I'm usually the supportive quiet type, until something needs to get done. Then, I turn into the business 'get it done' male mindset (Yes, I know I'm a woman - I hate to say it, but women have terrible ways of motivating people, if we want to motivate the world around us, we really have to tap into our inner male mindset).

Background - My (recent) background in programming is to be one of those crazy quality leads that knew nothing and was the best suited for the job. I learned a lot and all with a focus on the customer, which is perfect, because that is what business is about. While doing that I became a programmer, sort of. Had to release members of my team because I could program faster, more accurately, and with better results than the guys with the degrees... However, that doesn't mean that my team just wasn't qualified. Still wouldn't call myself a programmer as such, more of a manager that could pull off more focused results than the programmers.

Ruby/Marketing

If you need to learn Ruby check out _why. This author's style is beyond weird, however, my psychology background points out that it is extremely sound. Learn a bit, distract a bit, learn some more, and your subconscious and conscious minds will ensure that it all comes together quickly.
  Read his stuff at: http://mislav.uniqpath.com/poignant-guide/book/
  Who the hell is he at: http://en.wikipedia.org/wiki/Why_the_lucky_stiff
     and http://venturebeat.com/2013/04/19/why-oh-why/
  Is he going to come back? I hope so, but his website is back to being blank. At least we know he existed for a moment. I really hope he didn't sell out to Microsoft or pass away - but then, who else was showing him kindness and humanity... Kind of wouldn't blame him.
Was that marketing? Well, sort of.. Except Why's books are free and that is information sharing. Oh, yah, information sharing - that is what I was up to.

Concept

The concept? I'm out and about, have my phone/computer/whatever with me and it knows where I am. I don't know what businesses are around, so I ask Google. Right now Google tells me a bit about what's around me, but I wanted Google to tell me more. What businesses are within a short walk, what are their websites, phone numbers, and a short description? Can I, without walking, see their storefront and check out the inside of the business? I didn't get all of my answers, but as close as I can get without either paying for more API access or talking to a Google dev team rep. I might pay if the primary idea was that I was at home, my executive friend calls me, and I tell him about his area... Hrm. Anyway, I know it is an odd idea for people to want to know what is around them, however, I do.

Google and their API for places

The logic. You would think this would be truly easy. Google has an option for things close to you in their API, the issue is that the results are so limited in number, you might as well not get them.
*[] - indicates you need to fill this in. Use https://developers.google.com/places/documentation/search to help.

Google Places

Although it sounds wonderful, I found that the most useless results come from Google Places. The limit on results is incredibly low. So low that when I chose a mall as my testing point I could see more businesses with my eyes than they returned. However, it is a good way to start using the API as the cost is only 1 point to use it. So, I used it to start learning.
https://maps.googleapis.com/maps/api/place/nearbysearch/xml?key=[add your own key]&location=[lat and long in format 43.680934,-79.429741]&radius=10&sensor=false
*Note &types=food is a useful thing to add in.

Google Radar

First find where you are, use your cell phone coordinates or Google map or something. Here's a simple tool that will <a href="http://itouchmap.com/latlong.html">return your latitude and longitude</a>. Or you can just use the Google Reference number from the results of a search from the address or business.
Second, use Google Radar with a reference key or the latitude and longitude:
https://maps.googleapis.com/maps/api/place/radarsearch/json?key=[add your own key here]&sensor=false&location=53.541195,-113.490331&radius=1700
*Note if you're looking for food or something specific add on types &types=food|store|gym|doctor|dentist
**Keep results under 200, it will return a pretty random set of businesses within your radius.
***The results are cryptic. Keep the reference numbers and move on.

Google Place Details

This tool actually results in the details for the referenced location. This is the data I want, but notice that I have to do the search 200 times. Total daily search cost for one location works out to something like 205 API calls to receive what I want. Notice that I turned extensions on even though they are useless without paying Google. Still, I'll take whatever they will give me for free.
https://maps.googleapis.com/maps/api/place/details/xml?key=[add your own key]&sensor=false&extensions&reference=CnRnAAAABkIiDvc2RPQknkaJJclZfOmDfa9oRAavfKUoNlvYwtpakL2apCH29lc4M9IE8p9AX3VU1Ssn0QBPyvfBiCga3dFwi8HyMmGrgmmh93Zwc6Z2iWV3lUFLTsXLrgKPEjAGtzDObpKc56WBEN1NIhuTthIQeJDCi-f7W7LjZ9w_eHfGsBoU-_okOBQBpGWD1J66UJuLD6XXYmA

Resources

             The Internet - which, to be fair, is a good enough resource for any programmer
             The Über Geek that works with me... Except he has his own projects, still he's a good cheering section and he really has been one of the best people to work with. Just look up for long enough and he'll notice and find some way to elicit a smile. Although crass at times, Über Geek, you're the best cheering section ever - except my husband. Something about Shakespearean swears and odd rants keeps me with my man.

Toolchains, Google, and XML versus JSON results

A brief comment is required here. You can get the results above really easily. However, the future demands faster, smaller, and friendlier applications. I was hoping to use JSON. In the end, I abandoned it and my reasons follow.

Desired Chain

Java/Javascript with json results, perhaps some WebGL for fun, the Google API. Requirement jsonpath or xpath and Google API. Goal to appeal to both the "I love text info" and the "I love useful graphics" people.

Hurdles - JSON

OK, I like the concept of JSON. Beyond belief. I'm an executive and I was willing to spend a week trying to get a toolchain I liked working with it. That's a LOT of time for me and shows a bizarre level of commitment that my Über Geek pointed out to me is just ridiculous, give it up and move on. Let the Über Geeks sort it out later. Well, any json Über Geeks out there that will help me properly encode to the JSON RFC 4627 format are suddenly best friends. There's supposed to be a java file that does it. However, I couldn't find docs.
In the meantime, those unquoted bits kill the coolest and most widely adopted tools like json.parse and json.path. Although the browser itself and javascript basic still think they are JSON almost nothing else does and re-encoders are typically advanced regexp that have bug logs too long for me to consider. I'm not into the Google suggested search your way on down the lines of code thing. I want context without losing speed and quite frankly there is a reason bubble sort is still taught in programming and a reason for indexing. Results quickly please... Please? pretty please? No? OK, off to XML land, then. If I wanted to go line by line, I could get the same performance from perl, sed, aux, or grep with curl. Hashes and arrays are better, but still clunky and quite frankly, I don't have time for clunky. There are other options that are reasonable, I tried to get many of them working. All I can say is:
"Google, STOP BREAKING THE RULES and every developer's life will be so much sweeter. JSON will catch on as a faster, easier way than XML and all the XML fans will convert"
FYI: Whomever at Google thought it would be fun to return results without the quotes, since Google used to properly quote, you just made me despise you and your first born, but that's OK, it was only for a week, all is forgiven now.

Hurdles - Ruby

Really, ruby friends, you're dropping the ball on JSON, even in rails. And your included XML interpreter is still XML 1 and doesn't verify structures? Really? Come on. However, do I care that much? No, you had what I needed, just not what would have been cool. Thanks for reducing my workload and time spent based on limits of availability. However, I probably should have gone C#. I did try jsonpath in ruby and a few converters to see if I could get there. However, most converters convert the json into hash or array, so I was better off with XML. However, Ruby, love you to program in, I'm a fan of _why and so many other Ruby thinkers. However, wake up and take some of the JSON Kool-Aid and tons of the XML Kool-Aid.
Ruby 2.0.0 with 64 bit is where I headed. Should have stopped and thought about that. However, I have this brand new machine and wanted the latest. Suggestion to the next person, stick with 32, stay with older versions that still have SSL keys built in. However, keys were pretty easy to overcome. So, I'm not going to gripe that badly. Curl even makes it easy for every developer over at http://curl.haxx.se. Oh, and to all of you goofballs turning off SSL and calling that a fix, erm? Come on, really? Wow!

The Code Snippets that Make it Possible

#Set your requires. For my full project I needed:
require 'rubygems'
require 'openssl'
require 'net/https'
require 'rspec'
require 'rexml/document'

#Grab the SSL file
#Replace [FILE PATH] below with your own path.
Net::HTTP.start("curl.haxx.se") do |http|
  resp = http.get("/ca/cacert.pem")
  if resp.code == "200"
    open($cacert_file, "wb") { |file| file.write(resp.body) }
    puts "\n\nA bundle of certificate authorities has been installed to"
    puts "[FILE PATH]\n"
    puts "* Please set SSL_CERT_FILE in your current command prompt session with:"
    puts "     set SSL_CERT_FILE=[FILE PATH] + cacert.pem"
    puts "* To make this a permanent setting, add it to Environment Variables"
    puts "  under Control Panel -> Advanced -> Environment Variables"
    #or uncomment this line and set to the correct directory:
    #ENV['SSL_CERT_FILE'] = [FILE PATH] + "cacert.pem"
  else
    abort "\n\n>>>> A cacert.pem bundle could not be downloaded."
  end
end

#Parse your URI
$uri = URI.parse(your_html_api_call)

#Use a bit of code to make sure you actually obtain a result instead of a redirect
#by setting the limit to 1.
#You can use the same code to help out in finding redirects and still obtaining results
#if you need it, just raise the limit.

def fetch_ssl_body(your_html_api_call, limit)
  raise ArgumentError, 'This application does not allow redirects' if limit == 0
  http = Net::HTTP.new($uri.host, $uri.port)
  http.use_ssl = true
  http.cert = OpenSSL::X509::Certificate.new(File.read $cacert_file)
  request = Net::HTTP::Get.new(uri_str)
  response = http.request(request)
  case response
   when Net::HTTPSuccess then
      response.body
   when Net::HTTPRedirection then
      location = response['location']
      newLocation = location.gsub(Regexp.new(Regexp.escape($uri.to_s)),'')
      warn "redirected to #{location}"
      fetch(newLocation, limit - 1)
   else
      response.body
  end
end

#**everything above here was available from a previously trusted Ruby programmer, most of it was found directly on the Ruby site.

#Build an XML tree for parsing

include REXML
doc = Document.new fetch_ssl(your_html_api_call,1) #This always looks like it errors, expect undocumented
#puts doc #use this to prove to yourself you have a document
#shove only the data you want into something references = Array.new XPath.each( doc, "//reference") {|a| references << a.text}

End Notes

True, I didn't give you the whole app here, but this is all the code you need to build it. You can make calls and Ruby's each function will give you nice easy ways to iterate.

No comments:

Post a Comment