Ruby

作者 appwriteab3c90b37c95无许可证10 个星标收录于 2026年10月8日更新于 2026年10月8日仓库7周前更新

Appwrite Ruby SDK skill. Use when building server-side Ruby applications with Appwrite, including Rails and Sinatra integrations. Covers user management, database/table CRUD, file storage, and functions via API keys.

AI 生成的概览

指导使用 Appwrite SDK 构建服务端 Ruby 应用,涵盖用户、数据库、存储、团队、函数与 SSR 认证。

功能
该技能提供在服务端 Ruby 应用(包括 Rails 和 Sinatra 集成)中使用 Appwrite Ruby SDK 的参考说明与代码示例。内容涵盖使用 endpoint、project 和 API key 配置客户端,用户管理,表与行的 CRUD 及查询方法,文件存储,团队与成员,无服务器函数执行与处理函数,SSR 会话认证,错误处理,以及权限与角色配置。它产出的是指导与代码片段,而非可运行脚本。
适用场景
适用于编写或审查与 Appwrite 交互的 Ruby 服务端代码时,例如配置客户端、执行数据库或存储操作,或在 Rails、Sinatra 应用中实现基于会话的认证。也适用于配置 Appwrite 权限与角色或处理 SDK 错误时。
运行要求
需要 appwrite Ruby gem,以及带有 endpoint、project ID 和 API key 的 Appwrite 项目;需要访问 Appwrite API 的网络连接。该技能不包含脚本,只有说明与代码示例。

Appwrite Ruby SDK

Installation

bash
gem install appwrite

Setting Up the Client

ruby
require 'appwrite'
include Appwrite
client = Client.new    .set_endpoint('https://<REGION>.cloud.appwrite.io/v1')    .set_project(ENV['APPWRITE_PROJECT_ID'])    .set_key(ENV['APPWRITE_API_KEY'])

Code Examples

User Management

ruby
users = Users.new(client)
# Create useruser = users.create(user_id: ID.unique, email: '[email protected]', password: 'password123', name: 'User Name')
# List userslist = users.list(queries: [Query.limit(25)])
# Get userfetched = users.get(user_id: '[USER_ID]')
# Delete userusers.delete(user_id: '[USER_ID]')

Database Operations

Note: Use TablesDB (not the deprecated Databases class) for all new code. Only use Databases if the existing codebase already relies on it or the user explicitly requests it.

Tip: Prefer keyword arguments (e.g., database_id: '...') for all SDK method calls. Only use positional arguments if the existing codebase already uses them or the user explicitly requests it.

ruby
tables_db = TablesDB.new(client)
# Create databasedb = tables_db.create(database_id: ID.unique, name: 'My Database')
# Create rowdoc = tables_db.create_row(    database_id: '[DATABASE_ID]',    table_id: '[TABLE_ID]',    row_id: ID.unique,    data: { title: 'Hello World' })
# Query rowsresults = tables_db.list_rows(    database_id: '[DATABASE_ID]',    table_id: '[TABLE_ID]',    queries: [Query.equal('title', 'Hello World'), Query.limit(10)])
# Get rowrow = tables_db.get_row(database_id: '[DATABASE_ID]', table_id: '[TABLE_ID]', row_id: '[ROW_ID]')
# Update rowtables_db.update_row(    database_id: '[DATABASE_ID]',    table_id: '[TABLE_ID]',    row_id: '[ROW_ID]',    data: { title: 'Updated' })
# Delete rowtables_db.delete_row(database_id: '[DATABASE_ID]', table_id: '[TABLE_ID]', row_id: '[ROW_ID]')
String Column Types

Note: The legacy string type is deprecated. Use explicit column types for all new columns.

TypeMax charactersIndexingStorage
varchar16,383Full index (if size ≤ 768)Inline in row
text16,383Prefix onlyOff-page
mediumtext4,194,303Prefix onlyOff-page
longtext1,073,741,823Prefix onlyOff-page
  • varchar is stored inline and counts towards the 64 KB row size limit. Prefer for short, indexed fields like names, slugs, or identifiers.
  • text, mediumtext, and longtext are stored off-page (only a 20-byte pointer lives in the row), so they don't consume the row size budget. size is not required for these types.
ruby
# Create table with explicit string column typestables_db.create_table(    database_id: '[DATABASE_ID]',    table_id: ID.unique,    name: 'articles',    columns: [        { key: 'title',    type: 'varchar',    size: 255, required: true  },  # inline, fully indexable        { key: 'summary',  type: 'text',                  required: false },  # off-page, prefix index only        { key: 'body',     type: 'mediumtext',            required: false },  # up to ~4 M chars        { key: 'raw_data', type: 'longtext',              required: false },  # up to ~1 B chars    ])

Query Methods

ruby
# FilteringQuery.equal('field', 'value')             # == (or pass array for IN)Query.not_equal('field', 'value')         # !=Query.less_than('field', 100)             # <Query.less_than_equal('field', 100)       # <=Query.greater_than('field', 100)          # >Query.greater_than_equal('field', 100)    # >=Query.between('field', 1, 100)            # 1 <= field <= 100Query.is_null('field')                    # is nullQuery.is_not_null('field')                # is not nullQuery.starts_with('field', 'prefix')      # starts withQuery.ends_with('field', 'suffix')        # ends withQuery.contains('field', 'sub')            # containsQuery.search('field', 'keywords')         # full-text search (requires index)
# SortingQuery.order_asc('field')Query.order_desc('field')
# PaginationQuery.limit(25)                           # max rows (default 25, max 100)Query.offset(0)                           # skip N rowsQuery.cursor_after('[ROW_ID]')            # cursor pagination (preferred)Query.cursor_before('[ROW_ID]')
# Selection & LogicQuery.select(['field1', 'field2'])        # return only specified fieldsQuery.or([Query.equal('a', 1), Query.equal('b', 2)])   # ORQuery.and([Query.greater_than('age', 18), Query.less_than('age', 65)])  # AND (default)

File Storage

ruby
storage = Storage.new(client)
# Upload filefile = storage.create_file(bucket_id: '[BUCKET_ID]', file_id: ID.unique, file: InputFile.from_path('/path/to/file.png'))
# List filesfiles = storage.list_files(bucket_id: '[BUCKET_ID]')
# Delete filestorage.delete_file(bucket_id: '[BUCKET_ID]', file_id: '[FILE_ID]')
InputFile Factory Methods
ruby
InputFile.from_path('/path/to/file.png')             # from filesystem pathInputFile.from_string('Hello world', 'hello.txt')    # from string content

Teams

ruby
teams = Teams.new(client)
# Create teamteam = teams.create(team_id: ID.unique, name: 'Engineering')
# List teamslist = teams.list
# Create membership (invite user by email)membership = teams.create_membership(    team_id: '[TEAM_ID]',    roles: ['editor'],    email: '[email protected]')
# List membershipsmembers = teams.list_memberships(team_id: '[TEAM_ID]')
# Update membership rolesteams.update_membership(team_id: '[TEAM_ID]', membership_id: '[MEMBERSHIP_ID]', roles: ['admin'])
# Delete teamteams.delete(team_id: '[TEAM_ID]')

Role-based access: Use Role.team('[TEAM_ID]') for all team members or Role.team('[TEAM_ID]', 'editor') for a specific team role when setting permissions.

Serverless Functions

ruby
functions = Functions.new(client)
# Execute functionexecution = functions.create_execution(function_id: '[FUNCTION_ID]', body: '{"key": "value"}')
# List executionsexecutions = functions.list_executions(function_id: '[FUNCTION_ID]')
Writing a Function Handler (Ruby runtime)
ruby
# src/main.rb — Appwrite Function entry pointdef main(context)    # context.req.body         — raw body (String)    # context.req.body_json    — parsed JSON (Hash or nil)    # context.req.headers      — headers (Hash)    # context.req.method       — HTTP method    # context.req.path         — URL path    # context.req.query        — query params (Hash)
    context.log("Processing: #{context.req.method} #{context.req.path}")
    if context.req.method == 'GET'        return context.res.json({ message: 'Hello from Appwrite Function!' })    end
    context.res.json({ success: true })          # JSON    # context.res.text('Hello')                  # plain text    # context.res.empty                          # 204    # context.res.redirect('https://...')         # 302end

Server-Side Rendering (SSR) Authentication

SSR apps using Ruby frameworks (Rails, Sinatra, etc.) use the server SDK to handle auth. You need two clients:

  • Admin client — uses an API key, creates sessions, bypasses rate limits (reusable singleton)
  • Session client — uses a session cookie, acts on behalf of a user (create per-request, never share)
ruby
require 'appwrite'include Appwrite
# Admin client (reusable)admin_client = Client.new    .set_endpoint('https://<REGION>.cloud.appwrite.io/v1')    .set_project('[PROJECT_ID]')    .set_key(ENV['APPWRITE_API_KEY'])
# Session client (create per-request)session_client = Client.new    .set_endpoint('https://<REGION>.cloud.appwrite.io/v1')    .set_project('[PROJECT_ID]')
session = cookies['a_session_[PROJECT_ID]']session_client.set_session(session) if session
Email/Password Login (Sinatra)
ruby
post '/login' do    account = Account.new(admin_client)    session = account.create_email_password_session(        email: params[:email],        password: params[:password]    )
    # Cookie name must be a_session_<PROJECT_ID>    response.set_cookie('a_session_[PROJECT_ID]', {        value: session.secret,        httponly: true,        secure: true,        same_site: :strict,        path: '/',    })
    content_type :json    { success: true }.to_jsonend
Authenticated Requests
ruby
get '/user' do    session = request.cookies['a_session_[PROJECT_ID]']    halt 401, { error: 'Unauthorized' }.to_json unless session
    session_client = Client.new        .set_endpoint('https://<REGION>.cloud.appwrite.io/v1')        .set_project('[PROJECT_ID]')        .set_session(session)
    account = Account.new(session_client)    user = account.get
    content_type :json    user.to_jsonend
OAuth2 SSR Flow
ruby
# Step 1: Redirect to OAuth providerget '/oauth' do    account = Account.new(admin_client)    redirect_url = account.create_o_auth2_token(        provider: OAuthProvider::GITHUB,        success: 'https://example.com/oauth/success',        failure: 'https://example.com/oauth/failure'    )    redirect redirect_urlend
# Step 2: Handle callback — exchange token for sessionget '/oauth/success' do    account = Account.new(admin_client)    session = account.create_session(        user_id: params[:userId],        secret: params[:secret]    )
    response.set_cookie('a_session_[PROJECT_ID]', {        value: session.secret,        httponly: true, secure: true, same_site: :strict, path: '/',    })
    content_type :json    { success: true }.to_jsonend

Cookie security: Always use httponly, secure, and same_site: :strict to prevent XSS. The cookie name must be a_session_<PROJECT_ID>.

Forwarding user agent: Call session_client.set_forwarded_user_agent(request.user_agent) to record the end-user's browser info for debugging and security.

Error Handling

ruby
require 'appwrite'include Appwrite
begin    row = tables_db.get_row(database_id: '[DATABASE_ID]', table_id: '[TABLE_ID]', row_id: '[ROW_ID]')rescue Appwrite::Exception => e    puts e.message    # human-readable message    puts e.code       # HTTP status code (Integer)    puts e.type       # error type (e.g. 'document_not_found')    puts e.response   # full response body (Hash)end

Common error codes:

CodeMeaning
401Unauthorized — missing or invalid session/API key
403Forbidden — insufficient permissions
404Not found — resource does not exist
409Conflict — duplicate ID or unique constraint
429Rate limited — too many requests

Permissions & Roles (Critical)

Appwrite uses permission strings to control access to resources. Each permission pairs an action (read, update, delete, create, or write which grants create + update + delete) with a role target. By default, no user has access unless permissions are explicitly set at the row/file level or inherited from the table/bucket settings. Permissions are arrays of strings built with the Permission and Role helpers.

ruby
# Permission and Role are included in the main requirerequire 'appwrite'include Appwrite

Database Row with Permissions

ruby
doc = tables_db.create_row(    database_id: '[DATABASE_ID]',    table_id: '[TABLE_ID]',    row_id: ID.unique,    data: { title: 'Hello World' },    permissions: [        Permission.read(Role.user('[USER_ID]')),     # specific user can read        Permission.update(Role.user('[USER_ID]')),   # specific user can update        Permission.read(Role.team('[TEAM_ID]')),     # all team members can read        Permission.read(Role.any),                   # anyone (including guests) can read    ])

File Upload with Permissions

ruby
file = storage.create_file(    bucket_id: '[BUCKET_ID]',    file_id: ID.unique,    file: InputFile.from_path('/path/to/file.png'),    permissions: [        Permission.read(Role.any),        Permission.update(Role.user('[USER_ID]')),        Permission.delete(Role.user('[USER_ID]')),    ])

When to set permissions: Set row/file-level permissions when you need per-resource access control. If all rows in a table share the same rules, configure permissions at the table/bucket level and leave row permissions empty.

Common mistakes:

  • Forgetting permissions — the resource becomes inaccessible to all users (including the creator)
  • Role.any with write/update/delete — allows any user, including unauthenticated guests, to modify or remove the resource
  • Permission.read(Role.any) on sensitive data — makes the resource publicly readable

来源与署名

来源:appwrite/claude-plugin位于skills/ruby提交ab3c90b

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架