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!
Before we jump in, make sure you've got:
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!
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
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
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
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
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.
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
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
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
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
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! 🚀💎