I'm relatively new to Ruby and I came across some interesting behavior that I wanted some input on. I have a class that has some static headers, but the authorization token expires every so often, so I want it updated whenever I make a method call. Here's what I had originally:
require 'httparty'
require 'json'
module Connector
class Authentication
include HTTParty
base_uri "https://api.connector.com/v1"
headers "Content-Type" => "application/json"
headers "Accept" => "application/json"
def self.access_token
# This method returns the cached
# access_token unless it hasn't been set
# yet, in which case it requests a new
# one from the API.
...
end
end
class Users
include HTTParty
base_uri "https://api.connector.com/v1"
headers "Content-Type" => "application/json"
headers "Accept" => "application/json"
def self.create
data = {
...
}.to_json
resp = post("/users", :body => data, :headers => { "Authorization" => "Bearer #{ Connector::Authentication.access_token }" })
# Handle response
...
end
end
end
I was having issues when I tried to run
Connector::Users.create(). It took me a while to realize that by including the
:headers hash within the
post() method call, I was overriding the Content-Type and Accept headers set in the class definition. My solution for now was to remove the :headers hash from the
post() method call and just set it at the start of the my
create() method as follows:
class Users
include HTTParty
base_uri "https://api.connector.com/v1"
headers "Content-Type" => "application/json"
headers "Accept" => "application/json"
def self.create
# Update access_token before posting
headers "Authorization" => "Bearer #{ Connector::Authentication.access_token }"
# Perform post
data = {
...
}.to_json
resp = post("/users", :body => data)
# Handle response
...
end
end
Once I figured it out it made sense, but I felt like the behavior of overriding the previously set headers was a little strange. I readily recognize that I'm new to Ruby and I may just not understand certain conventions, of which this might be one. I wanted to get some feedback though and find out what others who are more experienced would do. Does my solution look Ruby-ish? Or would it have been more appropriate to do something like this:
post("/users", :body => data, :headers => default_options[:headers].merge({ "Authorization" => "Bearer #{ Connector::Authentication.access_token }" }))
Or, just maybe, is this behavior that should be altered so that :headers set within a request method are simply merged with the default_options[:headers]?