Back

Step by Step Guide to Building an Affinity API Integration in Ruby

Aug 18, 20247 minute read

Introduction

Hey there, fellow Ruby enthusiast! Ready to dive into the world of Affinity API integration? You're in for a treat. Affinity's API is a powerhouse for managing relationships and deals, and we're about to harness that power with our favorite language: Ruby. Let's get cracking!

Prerequisites

Before we jump in, make sure you've got:

  • A Ruby environment (2.5+ recommended)
  • Affinity API credentials (if you don't have these, hop over to Affinity's developer portal)

Setting up the project

First things first, let's set up our project:

mkdir affinity_integration cd affinity_integration bundle init

Now, open up that Gemfile and add:

gem 'httparty' gem 'dotenv'

Run bundle install, and we're off to the races!

Authentication

Affinity uses API keys for authentication. Create a .env file in your project root:

AFFINITY_API_KEY=your_api_key_here

Now, let's create a basic client:

require 'httparty' require 'dotenv/load' class AffinityClient include HTTParty base_uri 'https://api.affinity.co/v1' def initialize @options = { headers: { 'Authorization' => "Basic #{ENV['AFFINITY_API_KEY']}", 'Content-Type' => 'application/json' } } end end

Making API requests

Let's try a simple GET request:

def get_lists self.class.get('/lists', @options) end

To use it:

client = AffinityClient.new response = client.get_lists puts response.body

CRUD operations

Here's a quick rundown of CRUD operations:

# Create def create_person(data) self.class.post('/persons', @options.merge(body: data.to_json)) end # Read def get_person(id) self.class.get("/persons/#{id}", @options) end # Update def update_person(id, data) self.class.put("/persons/#{id}", @options.merge(body: data.to_json)) end # Delete def delete_person(id) self.class.delete("/persons/#{id}", @options) end

Error handling

Affinity API uses standard HTTP status codes. Let's add some error handling:

def handle_response(response) case response.code when 200..299 response when 400..499 raise "Client error: #{response.code} - #{response.body}" when 500..599 raise "Server error: #{response.code} - #{response.body}" else raise "Unknown error: #{response.code} - #{response.body}" end end

Now, wrap your API calls with this method:

def get_lists response = self.class.get('/lists', @options) handle_response(response) end

Rate limiting

Affinity has rate limits, so let's be good citizens:

def handle_rate_limit(response) if response.headers['X-RateLimit-Remaining'].to_i <= 1 sleep_time = response.headers['X-RateLimit-Reset'].to_i - Time.now.to_i sleep(sleep_time) if sleep_time > 0 end end

Add this to your handle_response method.

Pagination

Affinity uses cursor-based pagination. Here's how to handle it:

def get_all_lists lists = [] cursor = nil loop do response = get_lists(cursor) lists += response['lists'] cursor = response['next_cursor'] break if cursor.nil? end lists end def get_lists(cursor = nil) params = cursor ? { cursor: cursor } : {} self.class.get('/lists', @options.merge(query: params)) end

Advanced features

Webhooks

Affinity supports webhooks. Here's a basic Sinatra server to handle them:

require 'sinatra' require 'json' post '/webhook' do payload = JSON.parse(request.body.read) # Process the webhook payload status 200 end

Batch operations

For batch operations, you can use Ruby's concurrent-ruby gem to make parallel requests:

require 'concurrent' def batch_get_persons(ids) Concurrent::Promise.zip(*ids.map { |id| Concurrent::Promise.execute { get_person(id) } }).value end

Testing

For testing, you can use VCR to record and replay HTTP interactions:

require 'vcr' VCR.configure do |config| config.cassette_library_dir = "spec/fixtures/vcr_cassettes" config.hook_into :webmock end RSpec.describe AffinityClient do it "gets lists" do VCR.use_cassette("lists") do client = AffinityClient.new response = client.get_lists expect(response.code).to eq(200) end end end

Best practices

  1. Keep your API key secure. Never commit it to version control.
  2. Use environment variables for configuration.
  3. Implement proper error handling and logging.
  4. Respect rate limits and implement backoff strategies.
  5. Use pagination for large datasets.
  6. Implement proper testing, including mocking API responses.

Conclusion

And there you have it! You've just built a robust Affinity API integration in Ruby. From authentication to advanced features like webhooks and batch operations, you're now equipped to leverage the full power of Affinity's API.

Remember, this is just the beginning. As you build out your integration, you'll discover new ways to optimize and extend its functionality. Keep exploring, keep coding, and most importantly, have fun with it!

Happy coding, Rubyist! 🚀💎