Skip to content

codegestalt/zettel-box-ruby

Repository files navigation

ZettelBox Ruby Client

A Ruby client for the zettel.box REST API.

Installation

Add this line to your application's Gemfile:

gem "zettel_box"

And then execute:

bundle install

Configuration

Basic usage

require "zettel_box"

client = ZettelBox::Client.new(
  token: "your_api_token",
  box_slug: "bA1b2C3d4E5f6G7h8I9j0K1"
)

# List all zettels in a box
client.zettels.list

# Filter by type and visibility
client.zettels.list(type: "article", public: "true")

# Find a single zettel
client.zettels.find(slug: "zA1b2C3...")

# Search across boxes
client.search.zettels(q: "quantum biology", limit: 10)

# Box operations
client.boxes.list
client.boxes.find(slug: "bA1b2C3...")

Global configuration

ZettelBox::Client.configure do |config|
  config.token = "your_api_token"
  config.box_slug = "bA1b2C3d4E5f6G7h8I9j0K1"
  config.base_url = "https://app.zettel.box/api/v1"
  config.timeout = 30
  config.retries = 3
end

# All subsequent clients use the global configuration
client = ZettelBox::Client.new

Error handling

The client raises specific exceptions for different HTTP status codes:

Exception HTTP Status Description
ZettelBox::AuthenticationError 401 Invalid or missing API token
ZettelBox::ReadOnlyError 403 (read_only) Token has read-only access
ZettelBox::PermissionError 403 Insufficient permissions
ZettelBox::NotFoundError 404 Resource not found
ZettelBox::ValidationError 422 Validation failed (includes .errors hash)
ZettelBox::ParameterMissingError 422 (parameter_missing) Required parameter missing
ZettelBox::ServerError 5xx Server-side error
begin
  client.zettels.find(slug: "unknown")
rescue ZettelBox::NotFoundError
  # handle not found
end

Caching

The client supports pluggable caching via any object that responds to fetch(key, expires_in:, &block) and delete_matched(pattern).

Ruby on Rails with Redis

The easiest way to add caching in a Rails application is with the Redis cache store.

1. Add Redis to your Gemfile:

gem "redis", "~> 5.0"

2. Configure config.cache_store:

# config/environments/development.rb
config.cache_store = :redis_cache_store, {
  url: "redis://localhost:6379/1",
  expires_in: 5.minutes
}

# config/environments/production.rb
config.cache_store = :redis_cache_store, {
  url: ENV["REDIS_URL"],
  expires_in: 1.hour
}

3. Wire the client to Rails.cache in an initializer:

# config/initializers/zettel_box.rb
require "zettel_box"

ZettelBox::Client.configure do |config|
  config.token = Rails.application.credentials.dig(:zettel_box, :api_key)
  config.box_slug = Rails.application.credentials.dig(:zettel_box, :box_slug)
  config.base_url = Rails.application.credentials.dig(:zettel_box, :api_url)
  config.cache_store = Rails.cache
  config.cache_ttl = Rails.env.development? ? 5.minutes : 1.hour
end

4. Use the client in your models or controllers:

class Article
  def self.all
    client.zettels.list(type: "article", public: "true")
  end

  def self.find(slug)
    client.zettels.find(slug: slug)
  end

  private

  def self.client
    @client ||= ZettelBox::Client.new(
      skip_cache: Rails.env.development?
    )
  end
end

Ruby on Rails with Solid Cache

Rails 8 ships with Solid Cache, a database-backed cache that does not require Redis.

1. Add Solid Cache to your Gemfile:

gem "solid_cache"

2. Run the install generator:

bin/rails solid_cache:install

3. Configure the cache store:

# config/environments/production.rb
config.cache_store = :solid_cache_store

4. Wire the client as shown above.

Note: Solid Cache does not implement delete_matched by default. If you rely on client.clear_cache!, you may need to use Redis or implement a custom cache wrapper.

Skip cache

All read methods accept a skip_cache: true option to bypass the cache for a single request:

client.zettels.list(skip_cache: true)
client.zettels.find(slug: "z1", skip_cache: true)
client.boxes.list(skip_cache: true)

Clear cache

Invalidate all cached entries with the clear_cache! method:

client.clear_cache!

API Resources

Zettels

# List zettels
client.zettels.list                               # all
client.zettels.list(type: "article")              # filter by type
client.zettels.list(public: "true")               # filter by visibility
client.zettels.list(q: "quantum", limit: 10)      # search within box

# Find a zettel
client.zettels.find(slug: "zA1b2C3...")

# Create a zettel
client.zettels.create(title: "My Zettel", content_markdown: "# Hello")

# Update a zettel
client.zettels.update(slug: "zA1b2C3...", title: "Updated Title")

# Delete a zettel
client.zettels.delete(slug: "zA1b2C3...")

# Restore a soft-deleted zettel
client.zettels.restore(slug: "zA1b2C3...")

Boxes

# List boxes
client.boxes.list

# Find a box
client.boxes.find(slug: "bA1b2C3...")

# Create a box
client.boxes.create(name: "My Box", description: "A description")

# Update a box
client.boxes.update(slug: "bA1b2C3...", name: "New Name")

# Delete a box
client.boxes.delete(slug: "bA1b2C3...")

Search

# Search zettels across all accessible boxes
client.search.zettels(q: "grounding", limit: 5)

Development

Run the test suite:

bundle exec rake test

License

The gem is available as open source under the terms of the MIT License.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages