marcamillion marcamillion - 6 months ago 11
Ruby Question

How do I access an API service that doesn't have a Ruby gem?

So I want to access Glot.io that has just a barebones RESTful API from my Rails App.

Glot.io requires me to create an account and generates an API key for me -- pretty standard.

At a high-level, what is the best way for me to approach this?

Create an initializer file called

glot.rb
and what should I include there? Just my
ENV_VARS
to access the API service? Or do I not need that?

Then using the docs available to CREATE a snippet, what's the best approach to actually doing that? Should I use a CURL gem like curb to re-create this
POST
request?

curl --request POST \
--header 'Authorization: Token 99090-7abba-12389abcde' \
--header 'Content-type: application/json' \
--data '{"language": "python", "title": "test", "public": false, "files": [{"name": "main.py", "content": "print(42)"}]}' \
--url 'https://snippets.glot.io/snippets'


If so, what might the above look like?

Ideally I would love to get a high-level overview of the approach and then some code snippets of how I might proceed.

Answer

I would create a library (either create my own gem, or if just using it here, then in /lib) using net/http.

http://ruby-doc.org/stdlib-2.3.1/libdoc/net/http/rdoc/Net/HTTP.html

This is a very basic example, and could be done a number of ways. This example will allow you to to instantiate SnippetApi and set the URL. You can then call new_snippet, which will take the URL that you supplied, and make the API call.

To continue extending, you can change def new_snippet to def new_snippet(data), and then supply the data with your call.

Note: the filename should be snippet_api.rb to ensure that the "rails magic" works for autoloading.

lib/snippet_api.rb

require 'uri'
require 'net/http'
require 'net/https'

class SnippetApi

   def initialize(url, api_token = ENV['API_TOKEN'])
      @url = url
      @api_token = api_token
    end

    def url
      @url
    end

    def api_token
      @api_token
    end

  def new_snippet

    # https://snippets.glot.io/snippets
    uri = URI.parse(self.url)
    post_object = {'language': 'python', 'title': 'test', 'public': false, 'files': [{'name': 'main.py', 'content': 'print(42)'}]}

    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' => 'application/json', 'Authorization': "Token #{self.api_token}"})
    req.body = "[ #{post_object} ]"
    res = https.request(req)
    puts "Response #{res.code} #{res.message}: #{res.body}"
  end

end

Usage

2.3.0 :001 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets')
 => #<SnippetApi:0x00000003b6bc20 @url="https://snippets.glot.io/snippets"> 
2.3.0 :002 > snippet_api.new_snippet
Response 404 Not Found: {"message":"Wrong auth token"}

To ensure that files in /lib are loaded, be sure to add this to application.rb:

config.autoload_paths += Dir["#{config.root}/lib/**/"]

Usage with API Token

[brian@...]$ export API_TOKEN='token from env'

2.3.0 :001 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets')
 => #<SnippetApi:0x0000000342e8e0 @url="https://snippets.glot.io/snippets", @api_token="token from env"> 
2.3.0 :002 > snippet_api.api_token
 => "token from env" 
2.3.0 :003 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets','from init')
 => #<SnippetApi:0x000000033a60d0 @url="https://snippets.glot.io/snippets", @api_token="from init"> 
2.3.0 :004 > snippet_api.api_token
 => "from init" 

Edit 1: Added information about loading lib files.