Protocol Buffers works smoothly with Ruby and is perfect for Rails APIs, microservices, and background jobs. While Ruby developers often use JSON, Protobuf offers faster serialization and smaller message sizes, especially useful when building mobile backends or high-performance services.
This guide shows you how to get started with Protocol Buffers in Ruby. We'll use simple examples and keep things practical. See our Protobuf vs JSON comparison for performance benchmarks.
What You'll Need
- •Ruby: Version 2.7 or higher (check with
ruby -v) - •Bundler: Ruby gem manager (usually comes with Ruby)
- •Protocol Buffer Compiler: We'll install this next
Step 1: Install Protocol Buffers
First, install the protobuf compiler (protoc). On macOS:
brew install protobuf
On Ubuntu/Debian:
sudo apt update sudo apt install protobuf-compiler # Verify installation protoc --version
Next, add the Ruby protobuf gem to your Gemfile:
# Gemfile gem 'google-protobuf'
Install it:
bundle install
Step 2: Set Up Your Project
Create a simple Ruby project structure:
mkdir ruby-protobuf-demo cd ruby-protobuf-demo bundle init bundle add google-protobuf mkdir protos mkdir lib/generated -p
This creates a basic Ruby project with folders for proto files and generated code.
Step 3: Create Your .proto File
Create protos/subscriber.proto with a telecom subscriber example:
syntax = "proto3";
package telecom;
// Mobile subscriber information
message Subscriber {
string msisdn = 1; // Mobile number
string name = 2; // Subscriber name
string email = 3; // Email address
SubscriptionType type = 4; // Plan type
bool active = 5; // Account status
repeated string services = 6; // Active services
}
enum SubscriptionType {
PREPAID = 0;
POSTPAID = 1;
CORPORATE = 2;
}Step 4: Compile the .proto File
Generate Ruby code from your proto file:
protoc --ruby_out=lib/generated --proto_path=protos protos/subscriber.proto
This creates lib/generated/subscriber_pb.rb with the Ruby classes.
Step 5: Use Protocol Buffers in Ruby
Create example.rb:
require 'google/protobuf' require_relative 'lib/generated/subscriber_pb' # Create a new subscriber subscriber = Telecom::Subscriber.new( msisdn: '+91-9876543210', name: 'Telecom Customer', email: '[email protected]', type: :POSTPAID, active: true, services: ['Voice', 'Data', '4G LTE'] ) puts "Created subscriber: #{subscriber.name}" puts "MSISDN: #{subscriber.msisdn}" puts "Type: #{subscriber.type}" # Serialize to binary binary_data = Telecom::Subscriber.encode(subscriber) puts "Serialized to #{binary_data.bytesize} bytes" # Deserialize from binary decoded = Telecom::Subscriber.decode(binary_data) puts "\nDeserialized subscriber: #{decoded.name}" puts "Email: #{decoded.email}" puts "Active: #{decoded.active}" # Access repeated fields puts "\nActive services:" decoded.services.each do |service| puts " - #{service}" end
Step 6: Run Your Application
Run the Ruby script:
ruby example.rb
You should see output like:
Created subscriber: Telecom Customer MSISDN: +91-9876543210 Type: POSTPAID Serialized to 68 bytes Deserialized subscriber: Telecom Customer Email: [email protected] Active: true Active services: - Voice - Data - 4G LTE
Saving and Loading from Files
Save and load protobuf data:
require 'google/protobuf' require_relative 'lib/generated/subscriber_pb' # Create subscriber subscriber = Telecom::Subscriber.new( msisdn: '+91-9123456789', name: 'Network Admin', email: '[email protected]', type: :CORPORATE, active: true ) # Save to file File.open('subscriber.bin', 'wb') do |file| file.write(Telecom::Subscriber.encode(subscriber)) end puts "Saved to file" # Load from file binary_data = File.read('subscriber.bin') loaded = Telecom::Subscriber.decode(binary_data) puts "Loaded: #{loaded.name}" puts "MSISDN: #{loaded.msisdn}"
Convert Between JSON and Protobuf
Ruby protobuf supports JSON encoding and decoding:
require 'google/protobuf'
require_relative 'lib/generated/subscriber_pb'
# Create subscriber
subscriber = Telecom::Subscriber.new(
msisdn: '+91-9876543210',
name: 'Mobile User',
type: :PREPAID,
active: true
)
# Convert to JSON
json_string = Telecom::Subscriber.encode_json(subscriber)
puts "JSON output:"
puts json_string
# Parse from JSON
json_data = '{
"msisdn": "+91-9111111111",
"name": "New Subscriber",
"type": "POSTPAID",
"active": true
}'
new_subscriber = Telecom::Subscriber.decode_json(json_data)
puts "\nParsed from JSON: #{new_subscriber.name}"
puts "Type: #{new_subscriber.type}"Using Protobuf with Rails
Here's how to use Protobuf in a Rails API controller:
# app/controllers/subscribers_controller.rb
class SubscribersController < ApplicationController
require_relative '../../lib/generated/subscriber_pb'
def create
# Accept JSON, convert to Protobuf
subscriber = Telecom::Subscriber.new(
msisdn: params[:msisdn],
name: params[:name],
email: params[:email],
type: :POSTPAID,
active: true
)
# Save to database or process...
# Return protobuf binary
render body: Telecom::Subscriber.encode(subscriber),
content_type: 'application/x-protobuf'
end
def show
# Fetch subscriber from database
subscriber = Telecom::Subscriber.new(
msisdn: params[:id],
name: 'Retrieved Subscriber',
type: :PREPAID,
active: true
)
# Return as protobuf
render body: Telecom::Subscriber.encode(subscriber),
content_type: 'application/x-protobuf'
end
def parse
# Receive protobuf binary in request
binary_data = request.body.read
subscriber = Telecom::Subscriber.decode(binary_data)
# Process the subscriber
render json: {
name: subscriber.name,
msisdn: subscriber.msisdn,
type: subscriber.type.to_s
}
end
endBest Practices for Ruby
Use Symbols for Enums
In Ruby, protobuf enums work as symbols. Use :POSTPAID instead of strings for enum values.
Handle Binary Data Properly
When reading/writing files, always use binary mode ('wb' or'rb') to avoid encoding issues.
Keep Generated Files Separate
Store generated Ruby files in a dedicated directory and never edit them manually. They'll be overwritten on recompilation.
Use Class Methods
Use encode anddecode class methods for cleaner serialization code.
Common Issues
Issue: Cannot load generated file
Solution: Make sure you're using require_relative with the correct path to your generated _pb.rb file.
Issue: Encoding errors with binary data
Solution: Always use binary mode when reading/writing protobuf files. Use File.open('file.bin', 'wb') for writing.
Issue: protoc command not found
Solution: Install the Protocol Buffer compiler using Homebrew on macOS (brew install protobuf) or apt on Ubuntu.
Related Tools
Additional Resources
Official Documentation & References
- Official Ruby Protobuf Tutorial - Google's official Ruby guide
- Ruby Protobuf on GitHub - Source code and examples
- Protobuf on RubyGems - Ruby gem repository
Conclusion
Protocol Buffers fits naturally into Ruby's ecosystem. The Ruby gem provides a clean, idiomatic API that feels right at home in Ruby code. Whether you're building Rails APIs, Sinatra microservices, or background workers, protobuf offers solid performance benefits.
Start with these simple examples and gradually integrate protobuf into your Ruby applications. You'll notice the performance improvements especially when dealing with mobile clients or high-throughput services.