Backend Guide

This guide covers backend development for IDAH plugins using Ruby.

Overview

IDAH plugins can have backend services that process media files, export data, or integrate with external systems. Backend services are written in Ruby and follow a modular structure.

Technology Stack:

  • Language: Ruby 3.4+
  • Testing Framework: RSpec
  • Schema Validation: Verse Schema
  • Dependencies: Bundler

File Structure

<plugin_name>/
   └─ backends/
      ├─ README.md                               # Backend quick start guide
      ├─ spec_helper.rb                          # Shared RSpec configuration
      ├─ .rspec                                  # RSpec configuration
      ├─ media/                                  # Media service (if enabled)
      │  └─ <plugin_name_underscore>/
      │     └─ ..
      └─ sync/                                   # Sync service (if enabled)
         └─ <plugin_name_underscore>/
            └─ ..

Note: <plugin_name_underscore> is your plugin name in snake_case (e.g., my_awesome_plugin for plugin my-awesome-plugin).

Available Backend Services

IDAH plugins can include one, all, or none of these backend services. You can create frontend-only plugins, or add backend services as needed.

Media Service

Handles media file processing (images, videos, audio, etc.). Process original media files and generate thumbnails, previews, or transformations.

Sync Service

Handles data export and synchronization with external systems. Export datasets, entries, annotations, and media to various formats or external APIs.

Testing

Using RSpec

All backend code should have comprehensive tests:

media/processor_spec.rb
require "spec_helper"
require_relative "processor"

RSpec.describe YourPlugin::Processor do
  describe "#process" do
    it "processes media correctly" do
      options = YourPlugin::Options.new(quality: 90)
      processor = described_class.new(options)

      context = double("context",
        input_file: "input.jpg",
        output_file: "output.webp"
      )

      expect { processor.process(context) }.not_to raise_error
    end
  end
end

Running Tests

bundle exec rspec bundle exec rspec media/processor_spec.rb bundle exec rspec --format documentation

Best Practices

1. Module Naming

  • Use nested classes (YourPlugin::Media, YourPlugin::Sync) to avoid Zeitwerk conflicts
  • Follow Ruby naming conventions (PascalCase for classes, snake_case for files)

2. Error Handling

def process(context)
  raise ArgumentError, "Input file required" unless context.input_file

  begin
    # Processing logic
  rescue StandardError => e
    Verse.logger.error("Processing failed: #{e.message}")
    raise
  end
end

3. Logging

def process(context)
  Verse.logger.info("Starting processing for #{context.input_file}")
  # ... processing
  Verse.logger.info("Processing complete")
end

4. Performance

  • Process files in batches when possible
  • Use background jobs for long-running tasks
  • Clean up temporary files

5. Security

  • Validate all input options
  • Sanitize file paths
  • Use safe file operations
  • Don't expose sensitive data in logs

Debugging

Enable Debug Logging

Verse.logger.level = Logger::DEBUG

Use Pry for Debugging

require "pry"

def process(context)
  binding.pry  # Debugger breakpoint
  # ... rest of code
end

Common Patterns

Media Processing Pipeline

def process(context)
  validate_input(context.input_file)

  temp_file = create_temp_file

  begin
    transform(context.input_file, temp_file)
    optimize(temp_file, context.output_file)
  ensure
    cleanup(temp_file)
  end
end

Batch Export

def export(context)
  entries = fetch_entries(context.dataset)

  entries.each_slice(100) do |batch|
    export_batch(batch)
  end
end

Next Steps

Learn about specific backend implementations:

Resources

⚙️ Backend services ready! Explore media processing and data export guides.