Skip to main content

Quick Start: Your First Extension

Time: 15 minutes | Difficulty: Beginner | Prerequisites: Installation complete

Let's build a working Ruby gem with Rust. We'll create a string manipulation library that showcases Rust's speed and safety.

What We're Building

A FastStrings gem that provides:

  • String reversal
  • Safe Unicode handling
require "fast_strings"

FastStrings.reverse("Hello World!")
# => "!dlroW olleH"

Step 1: Create Your Gem

# Create a new gem with Rust support
bundle gem --ext=rust fast_strings
cd fast_strings
What did Bundler create?
fast_strings/
├── Gemfile # Ruby dependencies
├── fast_strings.gemspec # Gem metadata
├── Rakefile # Build tasks
├── ext/fast_strings/ # Rust extension
│ ├── Cargo.toml # Rust dependencies
│ ├── extconf.rb # Build configuration
│ └── src/
│ └── lib.rs # Rust code
└── lib/
└── fast_strings.rb # Ruby wrapper

Step 2: Write Your Rust Code

Replace the default code with our fast string implementation:

// ext/fast_strings/src/lib.rs
use magnus::{function, prelude::*, Error, Ruby};
use unicode_segmentation::UnicodeSegmentation;

/// Reverses a string preserving Unicode grapheme clusters
fn reverse_string(input: String) -> String {
input
.graphemes(true) // true = extended grapheme clusters
.rev()
.collect()
}

#[magnus::init]
fn init(ruby: &Ruby) -> Result<(), Error> {
let module = ruby.define_module("FastStrings")?;

// Define our module methods
module.define_singleton_method("reverse", function!(reverse_string, 1))?;

Ok(())
}

Add the Unicode dependency:

# ext/fast_strings/Cargo.toml
[package]
name = "fast_strings"
version = "0.1.0"
edition = "2021"

[dependencies]
magnus = { version = "0.7" }
unicode-segmentation = "1.10"

[lib]
name = "fast_strings"
crate-type = ["cdylib"]

Step 3: Build Your Extension

# Install dependencies and compile
bundle install
bundle exec rake compile
Compilation Steps
  1. Ruby reads extconf.rb
  2. create_rust_makefile generates a Makefile
  3. Cargo compiles your Rust code
  4. The compiled library is copied to lib/fast_strings/

Step 4: Add Tests

Create a test file to verify our implementation:

# test/test_fast_strings.rb
require "test_helper"

class TestFastStrings < Minitest::Test
def test_reverse_simple
assert_equal "dlrow olleh", FastStrings.reverse("hello world")
end

def test_reverse_unicode
assert_equal "!dlroW olleH", FastStrings.reverse("Hello World!")
end
end

Step 5: Run Tests

# Run the tests
bundle exec rake test

Step 6: Try It Yourself

# Open an interactive console
bundle exec bin/console
# Try the reverse function
FastStrings.reverse("Hello, World!")
# => "!dlroW ,olleH"

Publishing Your Gem

Ready to share your creation with the world?

# Update version in version.rb
# Update gemspec with description and homepage

# Build the gem
gem build fast_strings.gemspec

# Push to RubyGems.org
gem push fast_strings-0.1.0.gem

What You Learned

  • Created a Ruby gem with a Rust extension
  • Wrote safe, fast Rust code
  • Handled Unicode correctly
  • Added tests

Continue Learning

Core Concepts

Understand how rb-sys bridges Ruby and Rust

Project Setup

Structure larger projects properly

Working with Ruby Objects

Manipulate arrays, hashes, and more