Skip to content

Latest commit

 

History

History
260 lines (184 loc) · 5.59 KB

File metadata and controls

260 lines (184 loc) · 5.59 KB

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.