Skip to content

Ruby Examples

Generate OG images using Ruby.

Basic Generation

ruby
require 'net/http'
require 'json'
require 'uri'

def generate_og_image(params)
  uri = URI('https://ogimageapi.io/api/generate')
  
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  request = Net::HTTP::Post.new(uri.path)
  request['Content-Type'] = 'application/json'
  request['X-API-Key'] = ENV['OG_IMAGE_API_KEY']
  request.body = params.to_json
  
  response = http.request(request)
  
  if response.is_a?(Net::HTTPSuccess)
    response.body
  else
    raise "API Error: #{response.code} - #{response.body}"
  end
end

# Usage
image_data = generate_og_image(
  title: 'Hello from Ruby!',
  subtitle: 'Generated with OG Image API',
  template: 'default',
  theme: 'dark'
)

File.open('og-image.png', 'wb') { |f| f.write(image_data) }

Rails Integration

Service Class

ruby
# app/services/og_image_service.rb
class OgImageService
  API_URL = 'https://ogimageapi.io/api/generate'.freeze
  
  def initialize
    @api_key = Rails.application.credentials.og_image_api_key
  end
  
  def generate(params)
    uri = URI(API_URL)
    
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.read_timeout = 30
    
    request = Net::HTTP::Post.new(uri.path)
    request['Content-Type'] = 'application/json'
    request['X-API-Key'] = @api_key
    request.body = default_params.merge(params).to_json
    
    response = http.request(request)
    
    raise OgImageError, response.body unless response.is_a?(Net::HTTPSuccess)
    
    response.body
  end
  
  def generate_for_post(post)
    params = {
      title: post.title,
      subtitle: post.excerpt.truncate(200),
      author_name: post.author.name,
      author_avatar_url: post.author.avatar_url,
      template: 'blog',
      theme: 'dark'
    }
    
    generate(params)
  end
  
  private
  
  def default_params
    {
      template: 'default',
      theme: 'dark'
    }
  end
end

class OgImageError < StandardError; end

Active Storage Integration

ruby
# app/models/post.rb
class Post < ApplicationRecord
  has_one_attached :og_image
  
  after_save :generate_og_image, if: :should_regenerate_og?
  
  private
  
  def should_regenerate_og?
    saved_change_to_title? || saved_change_to_excerpt?
  end
  
  def generate_og_image
    GenerateOgImageJob.perform_later(id)
  end
end

Background Job

ruby
# app/jobs/generate_og_image_job.rb
class GenerateOgImageJob < ApplicationJob
  queue_as :default
  
  def perform(post_id)
    post = Post.find(post_id)
    service = OgImageService.new
    
    image_data = service.generate_for_post(post)
    
    post.og_image.attach(
      io: StringIO.new(image_data),
      filename: "og-#{post.slug}.png",
      content_type: 'image/png'
    )
  rescue OgImageError => e
    Rails.logger.error("OG Image generation failed for post #{post_id}: #{e.message}")
  end
end

Controller

ruby
# app/controllers/og_images_controller.rb
class OgImagesController < ApplicationController
  def show
    service = OgImageService.new
    
    image_data = service.generate(
      title: params[:title] || 'Default Title',
      subtitle: params[:subtitle],
      template: params[:template] || 'default',
      theme: params[:theme] || 'dark'
    )
    
    send_data image_data,
              type: 'image/png',
              disposition: 'inline'
  rescue OgImageError => e
    render json: { error: e.message }, status: :bad_request
  end
end

View Helper

ruby
# app/helpers/og_helper.rb
module OgHelper
  def og_meta_tags(title:, description:, image: nil, type: 'website')
    image_url = image || default_og_image_url
    
    content_tag(:head) do
      safe_join([
        tag(:meta, property: 'og:title', content: title),
        tag(:meta, property: 'og:description', content: description),
        tag(:meta, property: 'og:image', content: image_url),
        tag(:meta, property: 'og:type', content: type),
        tag(:meta, name: 'twitter:card', content: 'summary_large_image'),
        tag(:meta, name: 'twitter:title', content: title),
        tag(:meta, name: 'twitter:image', content: image_url)
      ])
    end
  end
  
  private
  
  def default_og_image_url
    asset_url('default-og.png')
  end
end

Sinatra Example

ruby
require 'sinatra'
require 'net/http'
require 'json'

get '/og' do
  title = params[:title] || 'Default Title'
  subtitle = params[:subtitle] || ''
  
  uri = URI('https://ogimageapi.io/api/generate')
  
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  request = Net::HTTP::Post.new(uri.path)
  request['Content-Type'] = 'application/json'
  request['X-API-Key'] = ENV['OG_IMAGE_API_KEY']
  request.body = {
    title: title,
    subtitle: subtitle,
    template: 'default',
    theme: 'dark'
  }.to_json
  
  response = http.request(request)
  
  content_type 'image/png'
  cache_control :public, max_age: 86400
  
  response.body
end

Batch Generation Script

ruby
#!/usr/bin/env ruby
require 'net/http'
require 'json'
require 'fileutils'

class OgBatchGenerator
  def initialize
    @api_key = ENV['OG_IMAGE_API_KEY']
    @output_dir = './og-images'
    FileUtils.mkdir_p(@output_dir)
  end
  
  def generate_batch(items)
    items.each_with_index do |item, index|
      puts "Generating #{index + 1}/#{items.length}: #{item[:slug]}"
      
      image_data = generate(item)
      save(item[:slug], image_data)
      
      # Rate limiting
      sleep(0.5)
    end
  end
  
  private
  
  def generate(params)
    uri = URI('https://ogimageapi.io/api/generate')
    
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    
    request = Net::HTTP::Post.new(uri.path)
    request['Content-Type'] = 'application/json'
    request['X-API-Key'] = @api_key
    request.body = params.except(:slug).to_json
    
    response = http.request(request)
    response.body
  end
  
  def save(slug, data)
    File.open("#{@output_dir}/#{slug}.png", 'wb') { |f| f.write(data) }
  end
end

# Usage
posts = [
  { slug: 'post-1', title: 'First Post', subtitle: 'Introduction', template: 'blog' },
  { slug: 'post-2', title: 'Second Post', subtitle: 'More content', template: 'blog' },
  { slug: 'post-3', title: 'Third Post', subtitle: 'Even more', template: 'blog' }
]

generator = OgBatchGenerator.new
generator.generate_batch(posts)

Generate stunning Open Graph images programmatically.