Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where would be a good place to store logic for a call to a third party api, based on Ruby on Rails best practices?

I am practicing making third-party api calls using the rest-client gem. Right now, my code for making a call to a third-party api is stored in a show method in my search_controller.rb. I'm assuming it would be better to store that logic somewhere other than a controller, in order to follow the "skinny controller" practice of ruby on rails. Where would be a better place to put this type of logic, or is this an ok place to have it?

like image 518
Kevin Brown Avatar asked Oct 16 '25 18:10

Kevin Brown


1 Answers

I would say two different kinds of objects in conjunction.

Clients

These are classes that simply do HTTP calls and touch the application boundary. The reason you want to isolate this in a discrete object is that it allows you mock it in tests. It also keeps the responsibilities clear.

# adapted from the HTTParty readme
class StackExchangeClient
  include HTTParty
  base_uri 'api.stackexchange.com'

  def initialize(service, page)
    @options = { query: { site: service, page: page } }
  end

  def questions
    self.class.get("/2.2/questions")
  end

  def users
    self.class.get("/2.2/users")
  end
end

/lib is a pretty good place to store clients since they rarely should contain any application specific logic.

Service objects

Service objects are Plain Old Ruby Objects (PORO) that are designed to execute one single action in your domain logic and do it well.
-- Rails Service Objects: A Comprehensive Guide

class QuestionImporterService
  def initialize(service, page, client: nil)
    @client = client || StackExchangeClient.new(service, page)
  end

  def call
     questions = @client.get_questions
     questions.map do |attributes|
       Question.new(attributes)
     end
  end
end

This example uses constructor injection to allow you to mock out the HTTP calls for testing.

You can place services in /app/services. Sometimes Spring gets "stuck" and does not pickup new folders in /app for autoloading in which case you restart it by calling $ spring stop.

like image 95
max Avatar answered Oct 18 '25 06:10

max



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!