Appearance
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; endActive 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
endBackground 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
endController
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
endView 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
endSinatra 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
endBatch 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)