Alayde Alayde - 10 months ago 37
reST (reStructuredText) Question

Consuming REST APIs in Ruby - When to authenticate?

I'll try to keep this as brief and to the point as possible.

I'm writing a Ruby gem, modeled after the Diplomat gem, that's a wrapper around a product's REST API. The API I'm consuming makes use of token based authentication; an API token is sent via a POST, and a session is returned as a cookie. I'm making use of the Faraday cookiejar middleware for handling the cookie that's returned by the API. The problem I'm struggling with, conceptually, is when to authenticate.

I have two classes, one called RestClient and one called Volume; the latter inherits from the former. As it stands now RestClient's init method builds a connection object and authenticates, while Volume's init method calls super and passes a path. My thinking here is that when any class that inherits from RestClient is initialized it'll authenticate the user.

class RestClient
def initialize(api_path)
<build connection>
def auth
<post token, get session cookie>

class Volume < RestClient
def initialize
def volumes
<send GET, receive volumes>

obj = #Creates object, authenticates user
obj.volumes #Returns list of volumes

I guess my question I headed down the right track? Should I hold off authenticating until a method is first called on the object, rather than authenticating when it's initialized? Am I going about this entirely incorrectly?

Answer Source

what you are asking here is more of a code-style question. there is no right or wrong here. i was about to vote to close because i think it is primarily opinion-based.

since i have an opinion, i'm writing an answer instead.

a) do not over-think

just implement the stuff, if it works, it is good enough

b) rule of 3

if you have implemented 3 things of the same kind and a pattern emerges, refactor!

c) refuse to use inheritance

when in doubt, do not use inheritance. a module will be good enough most of the time.

to your question specifically:

i would not use an initializer to make http calls. they are error-prone and error-handling from within initializers or around those is really ugly. it makes testing a pain in the ass.

what i would do is to just implement whatever you need in simple methods.

what is wrong with calling authenticate before making another api call? putting it into a block may make it really nice and readable:

client.authenticate do |session|

if this is too ugly for your use-case, you could do it lazily before any other method call that might require authentication.