### Basic Usage Example for GitHub Adapter with ActiveProject
Source: https://github.com/seuros/active_project/blob/master/README.md
This snippet provides a basic usage example for the GitHub adapter within the ActiveProject gem. It demonstrates how to initialize the adapter and perform common GitHub operations. The code is intended as a starting point for developers looking to integrate ActiveProject with GitHub.
```ruby
```ruby
# Example for GitHub adapter (placeholder)
# github_adapter = ActiveProject.adapter(:github)
# # ... further operations ...
```
```
--------------------------------
### Install ActiveProject Gem
Source: https://github.com/seuros/active_project/blob/master/README.md
Instructions for adding the ActiveProject gem to your application's Gemfile and installing it using Bundler, or installing it directly via the command line.
```ruby
gem 'activeproject'
```
```bash
$ bundle install
```
```bash
$ gem install activeproject
```
--------------------------------
### Configure GitHub Adapter for Webhooks
Source: https://context7.com/seuros/active_project/llms.txt
Configures the GitHub adapter with necessary parameters for processing webhooks, including repository details and webhook secret for verification. This setup is done via the ActiveProject.configure block.
```ruby
# Configure adapter with webhook secret
ActiveProject.configure do |config|
config.add_adapter(:github,
owner: "octocat",
repo: "hello-world",
access_token: ENV['GITHUB_ACCESS_TOKEN'],
webhook_secret: ENV['GITHUB_WEBHOOK_SECRET']
)
end
```
--------------------------------
### Enable Asynchronous I/O with ActiveProject Gem
Source: https://github.com/seuros/active_project/blob/master/README.md
This section explains how to enable non-blocking, asynchronous I/O in the ActiveProject gem by setting the `AP_DEFAULT_ADAPTER` environment variable to `async_http` before the process boots. It then provides a Ruby code example using `ActiveProject::Async.run` to perform parallel API calls to Jira, fetching issues from multiple boards concurrently using Ruby fibers.
```bash
AP_DEFAULT_ADAPTER=async_http
```
```ruby
ActiveProject::Async.run do |task|
jira = ActiveProject.adapter(:jira)
boards = %w[ACME DEV OPS]
tasks = boards.map do |key|
task.async { jira.list_issues(key, max_results: 100) }
end
issues = tasks.flat_map(&:wait)
puts "Fetched #{issues.size} issues in parallel."
end
```
--------------------------------
### Rails Async Scheduler Configuration and Usage
Source: https://context7.com/seuros/active_project/llms.txt
Demonstrates automatic async scheduler configuration for Rails applications using ActiveProject's Railtie. It shows how to opt out globally or via environment variables, and provides examples of using ActiveProject's async capabilities within Rails controllers for concurrent data fetching and within background jobs for data synchronization.
```ruby
class Application < Rails::Application
config.active_project.use_async_scheduler = false
end
# Or opt out via environment variable
# ENV['AP_NO_ASYNC_SCHEDULER'] = '1'
# Use in Rails controllers
class IssuesController < ApplicationController
def sync_all
# Async operations work automatically in Rails
ActiveProject::Async.run do |task|
adapters = [:jira, :github, :basecamp].map { |p| ActiveProject.adapter(p) }
tasks = adapters.map do |adapter|
task.async { adapter.list_projects }
end
@all_projects = tasks.flat_map(&:wait)
end
render json: @all_projects
end
end
# Background job integration
class SyncIssuesJob < ApplicationJob
def perform(project_key)
adapter = ActiveProject.adapter(:jira)
issues = adapter.list_issues(project_key, max_results: 1000)
issues.each do |issue|
LocalIssue.find_or_initialize_by(external_id: issue.id).update(
key: issue.key,
title: issue.title,
status: issue.status,
updated_at: issue.updated_at
)
end
end
end
```
--------------------------------
### Access Basecamp Platform-Specific Features
Source: https://context7.com/seuros/active_project/llms.txt
Demonstrates adding a comment with HTML-formatted content to Basecamp and accessing the raw data of the created comment. This example highlights the ability to work with rich text content specific to Basecamp.
```ruby
# Basecamp-specific: Access HTML content
basecamp = ActiveProject.adapter(:basecamp)
comment = basecamp.add_comment(
"123456",
"
HTML formatted content
",
{ project_id: "98765" }
)
puts "Raw HTML: #{comment.raw_data['content']}"
```
--------------------------------
### Configure Rails Auto-Scheduler in ActiveProject
Source: https://github.com/seuros/active_project/blob/master/README.md
This documentation explains how ActiveProject integrates with Rails applications by automatically installing `Async::Scheduler` before Zeitwerk boots. It provides instructions on how to opt out of this behavior either globally for the entire application in `config/application.rb` or on a per-environment basis using the `AP_NO_ASYNC_SCHEDULER` environment variable. It also mentions that ActiveProject detects and avoids interfering with schedulers already set up by other gems.
```ruby
# config/application.rb
config.active_project.use_async_scheduler = false
```
```bash
AP_NO_ASYNC_SCHEDULER=1
```
--------------------------------
### Process Jira Webhook
Source: https://context7.com/seuros/active_project/llms.txt
Handles incoming Jira webhooks by parsing the raw POST request body. This example focuses on the 'issue_created' event and accesses actor information. It does not include signature verification.
```ruby
# Jira webhook example (no signature verification)
def jira_webhook
adapter = ActiveProject.adapter(:jira)
webhook_event = adapter.parse_webhook(request.raw_post)
if webhook_event && webhook_event.type == :issue_created
issue_key = webhook_event.data[:object_key]
actor = webhook_event.actor
puts "#{actor.name} created issue #{issue_key}"
end
status 200
end
```
--------------------------------
### Access Resources via Factories (Jira Adapter)
Source: https://context7.com/seuros/active_project/llms.txt
Demonstrates using fluent factory patterns to access resources like projects and issues via the Jira adapter. Includes methods for retrieving all resources and finding specific ones by ID or key.
```ruby
adapter = ActiveProject.adapter(:jira)
# Projects factory
projects_factory = adapter.projects
all_projects = projects_factory.all
# => [#, ...]
first_project = projects_factory.find("ACME")
# => #
# Issues factory
issues_factory = adapter.issues
all_issues = issues_factory.all # Lists all issues
specific_issue = issues_factory.find("ACME-123")
# Access issues through project association
project = adapter.find_project("ACME")
project_issues = project.issues.all
# => [#, ...]
```
--------------------------------
### Access ActiveProject Adapters
Source: https://github.com/seuros/active_project/blob/master/README.md
Shows how to retrieve configured adapter instances for various project management platforms. Allows fetching default adapters or specifically named instances for different configurations.
```ruby
jira_primary = ActiveProject.adapter(:jira) # defaults to :primary
jira_secondary = ActiveProject.adapter(:jira, :secondary)
basecamp = ActiveProject.adapter(:basecamp) # defaults to :primary
trello = ActiveProject.adapter(:trello) # defaults to :primary
github = ActiveProject.adapter(:github) # defaults to :primary
github_project = ActiveProject.adapter(:github_project) # defaults to :primary
```
--------------------------------
### Configure ActiveProject Adapters
Source: https://github.com/seuros/active_project/blob/master/README.md
Demonstrates how to configure different project management adapters (Jira, Basecamp, Trello, GitHub) within the ActiveProject gem using environment variables for sensitive credentials. Supports named instances for multiple configurations of the same adapter.
```ruby
ActiveProject.configure do |config|
config.add_adapter :jira,
site_url: ENV["JIRA_SITE_URL"],
username: ENV["JIRA_USERNAME"],
api_token: ENV["JIRA_API_TOKEN"]
config.add_adapter :basecamp,
account_id: ENV["BASECAMP_ACCOUNT_ID"],
access_token: ENV["BASECAMP_ACCESS_TOKEN"]
config.add_adapter :trello,
key: ENV["TRELLO_KEY"],
token: ENV["TRELLO_TOKEN"]
# GitHub Projects – real Issues/PRs only
config.add_adapter :github_project,
access_token: ENV["GITHUB_TOKEN"]
# GitHub primary instance
config.add_adapter :github,
owner: ENV["GITHUB_OWNER"],
repo: ENV["GITHUB_REPO"],
access_token: ENV["GITHUB_ACCESS_TOKEN"],
webhook_secret: ENV["GITHUB_WEBHOOK_SECRET"]
end
```
--------------------------------
### Jira Adapter: List, Create, Update, and Comment on Issues
Source: https://github.com/seuros/active_project/blob/master/README.md
This Ruby snippet demonstrates fetching the Jira adapter, listing projects, retrieving issues, creating a new issue, updating an existing one, and adding a comment. It includes robust error handling for common Jira API issues like authentication, not found, validation, and general API errors.
```ruby
jira_adapter = ActiveProject.adapter(:jira)
begin
# List projects
projects = jira_adapter.list_projects
puts "Found #{projects.count} projects."
first_project = projects.first
if first_project
puts "Listing issues for project: #{first_project.key}"
# List issues in the first project
issues = jira_adapter.list_issues(first_project.key, max_results: 5)
puts "- Found #{issues.count} issues (showing max 5)."
# Find a specific issue (replace 'PROJ-1' with a valid key)
# issue_key_to_find = 'PROJ-1'
# issue = jira_adapter.find_issue(issue_key_to_find)
# puts "- Found issue: #{issue.key} - #{issue.title}"
# Create a new issue
puts "Creating a new issue..."
new_issue_attributes = {
project: { key: first_project.key },
summary: "New task from ActiveProject Gem #{Time.now}",
issue_type: { name: 'Task' }, # Ensure 'Task' is a valid issue type name
description: "This issue was created via the ActiveProject gem."
}
created_issue = jira_adapter.create_issue(first_project.key, new_issue_attributes)
puts "- Created issue: #{created_issue.key} - #{created_issue.title}"
# Update the issue
puts "Updating issue #{created_issue.key}..."
updated_issue = jira_adapter.update_issue(created_issue.key, { summary: "[Updated] #{created_issue.title}" })
puts "- Updated summary: #{updated_issue.title}"
# Add a comment
puts "Adding comment to issue #{updated_issue.key}..."
comment = jira_adapter.add_comment(updated_issue.key, "This is a comment added via the ActiveProject gem.")
puts "- Comment added with ID: #{comment.id}"
end
rescue ActiveProject::AuthenticationError => e
puts "Error: Jira Authentication Failed - #{e.message}"
rescue ActiveProject::NotFoundError => e
puts "Error: Resource Not Found - #{e.message}"
rescue ActiveProject::ValidationError => e
puts "Error: Validation Failed - #{e.message} (Details: #{e.errors})"
rescue ActiveProject::ApiError => e
puts "Error: Jira API Error (#{e.status_code}) - #{e.message}"
rescue => e
puts "An unexpected error occurred: #{e.message}"
end
```
--------------------------------
### Configure ActiveProject Adapters
Source: https://context7.com/seuros/active_project/llms.txt
Configures various project management API adapters (Jira, Basecamp, Trello, GitHub Projects, GitHub Repositories) with their respective credentials. Supports named instances for multiple accounts of the same service. Accesses configured adapters using `ActiveProject.adapter`.
```ruby
ActiveProject.configure do |config|
# Jira Cloud or Server (REST v3)
config.add_adapter :jira,
site_url: "https://yourcompany.atlassian.net",
username: "user@example.com",
api_token: "your_jira_api_token"
# Basecamp (REST v3+)
config.add_adapter :basecamp,
account_id: "1234567",
access_token: "your_basecamp_access_token"
# Trello (REST API)
config.add_adapter :trello,
key: "your_trello_api_key",
token: "your_trello_token"
# GitHub Projects V2 (GraphQL v4)
config.add_adapter :github_project,
access_token: "ghp_your_github_token"
# GitHub Repository (REST v3)
config.add_adapter :github,
owner: "octocat",
repo: "hello-world",
access_token: "ghp_your_github_token",
webhook_secret: "your_webhook_secret_optional"
# Named instances for multiple accounts
config.add_adapter :jira, :secondary,
site_url: "https://other-jira.atlassian.net",
username: "other@example.com",
api_token: "other_jira_token"
end
# Access configured adapters
jira_adapter = ActiveProject.adapter(:jira) # defaults to :primary
secondary_jira = ActiveProject.adapter(:jira, :secondary)
github_adapter = ActiveProject.adapter(:github)
```
--------------------------------
### Persist and Update Resources (Jira Adapter)
Source: https://context7.com/seuros/active_project/llms.txt
Shows how to create, save, update, and delete resources like issues using an ActiveRecord-like API with the Jira adapter. New resources are created locally first and then persisted to the remote API.
```ruby
adapter = ActiveProject.adapter(:jira)
# Create new issue without immediate persistence
issue = ActiveProject::Resources::Issue.new(adapter, {
project_id: "ACME",
title: "New feature request",
description: "Add export functionality"
})
# Persist to remote API
issue.save
# => true
# Now issue.id and issue.key are populated
# Update attributes and save
issue.title = "Updated feature request"
issue.description = "Add export to CSV and JSON"
issue.save
# => true
# Update with hash
issue.update({ title: "Export feature - Phase 1" })
# => true
# Delete remote record
issue.delete
# => true (issue is now frozen)
```
--------------------------------
### Manage GitHub Repository Issues with ActiveProject Gem
Source: https://github.com/seuros/active_project/blob/master/README.md
This Ruby code snippet demonstrates how to interact with a GitHub repository using the ActiveProject gem's GitHub adapter. It covers listing projects (repositories), listing, finding, creating, updating, adding comments to, and closing issues. Error handling for common GitHub API issues is also included.
```ruby
github_adapter = ActiveProject.adapter(:github)
begin
# List projects (will return the configured repository)
projects = github_adapter.list_projects
puts "Found #{projects.count} GitHub repository."
repo = projects.first
if repo
puts "Working with repository: #{repo.key} (#{repo.name})"
# List issues in the repository
issues = github_adapter.list_issues(repo.key)
puts "- Found #{issues.count} issues."
# Find a specific issue (replace '1' with a valid issue number)
# issue_number = 1
# issue = github_adapter.find_issue(issue_number.to_s)
# puts "- Found issue: ##{issue.key} - #{issue.title}"
# Create a new issue
puts "Creating a new issue..."
new_issue_attributes = {
title: "New issue from ActiveProject Gem #{Time.now}",
description: "This issue was created via the ActiveProject gem.",
assignees: [{ name: "username" }] # Optional: Provide GitHub usernames for assignees
}
created_issue = github_adapter.create_issue(repo.key, new_issue_attributes)
puts "- Created issue: ##{created_issue.key} - #{created_issue.title}"
# Update the issue
puts "Updating issue ##{created_issue.key}..."
updated_issue = github_adapter.update_issue(created_issue.key, { title: "[Updated] #{created_issue.title}" })
puts "- Updated title: #{updated_issue.title}"
# Add a comment
puts "Adding comment to issue ##{updated_issue.key}..."
comment = github_adapter.add_comment(updated_issue.key, "This is a comment added via the ActiveProject gem.")
puts "- Comment added with ID: #{comment.id}"
# Close the issue
puts "Closing issue ##{updated_issue.key}..."
closed_issue = github_adapter.update_issue(updated_issue.key, { state: "closed" })
puts "- Issue closed, status: #{closed_issue.status}"
end
rescue ActiveProject::AuthenticationError => e
puts "Error: GitHub Authentication Failed - #{e.message}"
rescue ActiveProject::NotFoundError => e
puts "Error: Resource Not Found - #{e.message}"
rescue ActiveProject::ValidationError => e
puts "Error: Validation Failed - #{e.message}"
rescue ActiveProject::RateLimitError => e
puts "Error: GitHub Rate Limit Exceeded - #{e.message}"
rescue ActiveProject::ApiError => e
puts "Error: GitHub API Error (#{e.status_code}) - #{e.message}"
rescue => e
puts "An unexpected error occurred: #{e.message}"
end
```
--------------------------------
### Interact with Basecamp API using ActiveProject Gem
Source: https://github.com/seuros/active_project/blob/master/README.md
This Ruby code snippet demonstrates how to configure and use the Basecamp adapter to list projects and issues. It includes error handling for common Basecamp API issues such as authentication failures, not found resources, validation errors, rate limits, and general API errors. It also shows how to create a new issue (To-do) but notes that finding, updating, and commenting on issues currently requires project_id context and may raise NotImplementedError.
```ruby
basecamp_adapter = ActiveProject.adapter(:basecamp)
try
# List projects
projects = basecamp_adapter.list_projects
puts "Found #{projects.count} Basecamp projects."
first_project = projects.first
if first_project
puts "Listing issues (To-dos) for project: #{first_project.name} (ID: #{first_project.id})"
# List issues (To-dos) in the first project
# Note: This lists across all to-do lists in the project
issues = basecamp_adapter.list_issues(first_project.id)
puts "- Found #{issues.count} To-dos."
# Create a new issue (To-do)
# IMPORTANT: You need a valid todolist_id for the target project.
# You might need another API call to find a todolist_id first.
# todolist_id_for_test = 1234567 # Replace with a real ID
# puts "Creating a new To-do..."
# new_issue_attributes = {
# todolist_id: todolist_id_for_test,
# title: "New BC To-do from ActiveProject Gem #{Time.now}",
# description: "HTML description for the to-do."
# }
# created_issue = basecamp_adapter.create_issue(first_project.id, new_issue_attributes)
# puts "- Created To-do: #{created_issue.id} - #{created_issue.title}"
# --- Operations requiring project_id context (Currently raise NotImplementedError) ---
# puts "Finding, updating, and commenting require project_id context and are currently not directly usable via the base interface."
#
# # Find a specific issue (To-do) - Requires project_id context
# # todo_id_to_find = created_issue.id
# # issue = basecamp_adapter.find_issue(todo_id_to_find) # Raises NotImplementedError
#
# # Update the issue (To-do) - Requires project_id context
# # updated_issue = basecamp_adapter.update_issue(created_issue.id, { title: "[Updated] #{created_issue.title}" }) # Raises NotImplementedError
#
# # Add a comment - Requires project_id context
# # comment = basecamp_adapter.add_comment(created_issue.id, "This is an HTML comment.") # Raises NotImplementedError
end
rescue ActiveProject::AuthenticationError => e
puts "Error: Basecamp Authentication Failed - #{e.message}"
rescue ActiveProject::NotFoundError => e
puts "Error: Basecamp Resource Not Found - #{e.message}"
rescue ActiveProject::ValidationError => e
puts "Error: Basecamp Validation Failed - #{e.message}"
rescue ActiveProject::RateLimitError => e
puts "Error: Basecamp Rate Limit Exceeded - #{e.message}"
rescue ActiveProject::ApiError => e
puts "Error: Basecamp API Error (#{e.status_code}) - #{e.message}"
rescue NotImplementedError => e
puts "Error: Method requires project_id context which is not yet implemented: #{e.message}"
rescue => e
puts "An unexpected error occurred: #{e.message}"
end
```
--------------------------------
### Process GitHub Webhooks with ActiveProject Gem
Source: https://github.com/seuros/active_project/blob/master/README.md
This Ruby code demonstrates how to configure and process GitHub webhooks using the ActiveProject gem. It includes verifying webhook signatures and parsing incoming events like issue creation, updates, and comments into a standardized format for further processing.
```ruby
# Configure the adapter with a webhook secret (same secret used in GitHub webhook settings)
ActiveProject.configure do |config|
config.add_adapter(:github,
owner: ENV.fetch('GITHUB_OWNER'),
repo: ENV.fetch('GITHUB_REPO'),
access_token: ENV.fetch('GITHUB_ACCESS_TOKEN'),
webhook_secret: ENV.fetch('GITHUB_WEBHOOK_SECRET', nil)
)
end
# In your webhook endpoint (e.g., in a Rails controller)
def github_webhook
adapter = ActiveProject.adapter(:github)
# Get the raw request body and signature header
request_body = request.raw_post
signature = request.headers['X-Hub-Signature-256']
# Verify the webhook signature (if webhook_secret is configured)
if adapter.verify_webhook_signature(request_body, signature)
# Parse the webhook payload into a standardized WebhookEvent
event_headers = {
'X-GitHub-Event' => request.headers['X-GitHub-Event'],
'X-GitHub-Delivery' => request.headers['X-GitHub-Delivery']
}
webhook_event = adapter.parse_webhook(request_body, event_headers)
if webhook_event
# Process different event types
case webhook_event.type
when :issue_created
issue = webhook_event.data[:issue]
puts "New issue created: ##{issue.key} - #{issue.title}"
when :issue_updated, :issue_closed, :issue_reopened
issue = webhook_event.data[:issue]
puts "Issue ##{issue.key} was #{webhook_event.type.to_s.sub('issue_', '')}"
when :comment_created
comment = webhook_event.data[:comment]
issue = webhook_event.data[:issue]
puts "New comment on issue ##{issue.key}: #{comment.body.truncate(50)}"
end
# The webhook was successfully processed
head :ok
else
# The webhook payload couldn't be parsed
head :unprocessable_entity
end
else
# The webhook signature verification failed
head :forbidden
end
end
```
--------------------------------
### ActiveProject Projects API - Manage Projects
Source: https://context7.com/seuros/active_project/llms.txt
Provides unified CRUD operations for projects across different platforms. Includes listing all projects, finding a specific project by key, accessing project attributes, creating new projects with platform-specific details, and deleting projects. Requires an adapter instance.
```ruby
# List all projects (Jira Projects, Basecamp Projects, Trello Boards, GitHub Repos)
adapter = ActiveProject.adapter(:jira)
projects = adapter.list_projects
# => [#, ...]
# Find a specific project
project = adapter.find_project("ACME")
# => #
# Access project attributes
puts "Project: #{project.name} (#{project.key})"
puts "Adapter source: #{project.adapter_source}" # => :jira
# Create a new project (platform-specific attributes)
new_project = adapter.create_project({
key: "NEWPROJ",
name: "New Project",
project_type_key: "software",
lead_account_id: "557058:abc123..."
})
# Delete a project (use with caution)
adapter.delete_project("NEWPROJ")
# => true
```
--------------------------------
### Test Adapter Connectivity
Source: https://context7.com/seuros/active_project/llms.txt
Verifies adapter connectivity and authentication for various platforms. Includes checking connection status, retrieving the currently authenticated user, and iterating through multiple platforms to report connection success or failure.
```ruby
# Check if adapter can authenticate
adapter = ActiveProject.adapter(:jira)
if adapter.connected?
puts "Successfully connected to Jira"
current_user = adapter.get_current_user
puts "Authenticated as: #{current_user.name} (#{current_user.email})"
else
puts "Failed to connect - check credentials"
end
# Test multiple adapters
[:jira, :github, :basecamp, :trello].each do |platform|
begin
adapter = ActiveProject.adapter(platform)
if adapter.connected?
user = adapter.get_current_user
puts "✓ #{platform}: #{user.name}"
else
puts "✗ #{platform}: Authentication failed"
end
rescue ActiveProject::Error => e
puts "✗ #{platform}: #{e.message}"
end
end
```
--------------------------------
### Perform Asynchronous API Calls with Fibers
Source: https://context7.com/seuros/active_project/llms.txt
Enables parallel API calls using fiber-based concurrency by setting the AP_DEFAULT_ADAPTER environment variable to 'async_http'. Demonstrates running tasks in parallel and collecting results.
```ruby
# Enable async adapter via environment variable before process boots
# ENV['AP_DEFAULT_ADAPTER'] = 'async_http'
ActiveProject::Async.run do |task|
jira = ActiveProject.adapter(:jira)
project_keys = %w[ACME BETA GAMMA DELTA]
# Create async tasks for parallel execution
tasks = project_keys.map do |key|
task.async { jira.list_issues(key, max_results: 100) }
end
# Wait for all tasks to complete
all_issues = tasks.flat_map(&:wait)
puts "Fetched #{all_issues.size} issues from #{project_keys.size} projects in parallel"
# No threads, no mutexes - just Ruby fibers
end
# Parallel operations with error handling
ActiveProject::Async.run do |task|
adapters = {
jira: ActiveProject.adapter(:jira),
github: ActiveProject.adapter(:github),
basecamp: ActiveProject.adapter(:basecamp)
}
results = adapters.map do |name, adapter|
task.async do
begin
{ name: name, projects: adapter.list_projects }
rescue ActiveProject::Error => e
{ name: name, error: e.message }
end
end
end.map(&:wait)
results.each do |result|
if result[:error]
puts "#{result[:name]}: ERROR - #{result[:error]}"
else
puts "#{result[:name]}: #{result[:projects].size} projects"
end
end
end
```
--------------------------------
### Interact with Basecamp Adapter
Source: https://context7.com/seuros/active_project/llms.txt
Adds a comment to a Basecamp to-do item. Requires project_id context. The adapter is initialized using ActiveProject.adapter(:basecamp).
```ruby
basecamp_adapter = ActiveProject.adapter(:basecamp)
comment = basecamp_adapter.add_comment(
"123456789", # todo_id
"Great work! Let's deploy this.",
{ project_id: "98765" }
)
```
--------------------------------
### ActiveProject Architecture Diagram
Source: https://github.com/seuros/active_project/blob/master/README.md
Visual representation of the ActiveProject's architectural structure, highlighting the main gem and its adapter sub-components for different platforms like Jira, Basecamp, Trello, and GitHub.
```text
ActiveProject
└── Adapters
├── JiraAdapter
├── BasecampAdapter
├── TrelloAdapter
├── GithubProjectAdapter
└── GithubAdapter
```
--------------------------------
### Normalize Jira Statuses
Source: https://context7.com/seuros/active_project/llms.txt
Demonstrates how to manage and normalize status information for Jira projects. Includes checking status validity, retrieving all valid statuses, converting platform-specific statuses to standard symbols, and converting standard symbols back to platform formats. Status normalization is also automatic when fetching issues.
```ruby
adapter = ActiveProject.adapter(:jira)
# Check if a status is valid for the platform
adapter.status_known?("ACME", :in_progress)
# => true
# Get all valid statuses for a project
statuses = adapter.valid_statuses("ACME")
# => [:open, :in_progress, :blocked, :on_hold, :closed]
# Normalize platform-specific status to standard symbol
normalized = adapter.normalize_status("In Development", project_id: "ACME")
# => :in_progress
# Convert normalized status back to platform format
platform_status = adapter.denormalize_status(:closed, project_id: "ACME")
# => "Done" (for Jira) or "closed" (for GitHub)
# Status is automatically normalized when fetching issues
issue = adapter.find_issue("ACME-123")
case issue.status
when :open
puts "Ready to start"
when :in_progress
puts "Work in progress"
when :closed
puts "Completed"
end
```
--------------------------------
### Process GitHub Webhook in Rails/Sinatra
Source: https://context7.com/seuros/active_project/llms.txt
Handles incoming GitHub webhooks by verifying the signature, parsing the payload into a standardized event, and processing different event types like issue creation or updates. Requires the raw request body and signature header.
```ruby
def github_webhook
adapter = ActiveProject.adapter(:github)
# Verify webhook signature (prevents spoofing)
request_body = request.raw_post
signature = request.headers['X-Hub-Signature-256']
unless adapter.verify_webhook_signature(request_body, signature)
halt 403, "Invalid signature"
end
# Parse webhook payload into standardized event
event_headers = {
'X-GitHub-Event' => request.headers['X-GitHub-Event'],
'X-GitHub-Delivery' => request.headers['X-GitHub-Delivery']
}
webhook_event = adapter.parse_webhook(request_body, event_headers)
if webhook_event
# Process different event types
case webhook_event.type
when :issue_created
issue = webhook_event.data[:issue]
notify_team("New issue: ##{issue.key} - #{issue.title}")
when :issue_updated
issue = webhook_event.data[:issue]
changes = webhook_event.data[:changes] || {}
log_audit("Issue #{issue.key} updated", changes)
when :issue_closed
issue = webhook_event.data[:issue]
update_metrics(issue)
when :comment_created
comment = webhook_event.data[:comment]
issue = webhook_event.data[:issue]
notify_subscribers(issue, comment)
end
# Access webhook metadata
puts "Event type: #{webhook_event.type}"
puts "Resource: #{webhook_event.resource_type} (#{webhook_event.resource_id})"
puts "Project: #{webhook_event.project_id}"
puts "Source adapter: #{webhook_event.source}"
status 200
else
status 422 # Unprocessable webhook
end
end
```
--------------------------------
### Access Trello Platform-Specific Features
Source: https://context7.com/seuros/active_project/llms.txt
Shows how to retrieve Trello-specific information such as labels and board ID from a card's raw data. This involves accessing arrays and nested objects within the `raw_data` hash.
```ruby
# Trello-specific: Access labels and board info
trello = ActiveProject.adapter(:trello)
issue = trello.find_issue("abc123") # Trello card
labels = issue.raw_data["labels"].map { |l| l["name"] }
board_id = issue.raw_data["idBoard"]
puts "Labels: #{labels.join(', ')}"
puts "Board ID: #{board_id}"
```
--------------------------------
### Access Jira Platform-Specific Features
Source: https://context7.com/seuros/active_project/llms.txt
Illustrates accessing Jira-specific data, including custom fields like 'Story Points' and 'Sprint'. It uses the `dig` method for safe navigation into nested hash structures within the raw issue data.
```ruby
# Jira-specific: Access custom fields
jira = ActiveProject.adapter(:jira)
issue = jira.find_issue("ACME-123")
story_points = issue.raw_data.dig("fields", "customfield_10016")
sprint = issue.raw_data.dig("fields", "customfield_10020")
puts "Story points: #{story_points}"
puts "Sprint: #{sprint&.first&.dig('name')}"
```
--------------------------------
### ActiveProject Issues API - Manage Issues
Source: https://context7.com/seuros/active_project/llms.txt
Enables unified CRUD operations for issues, tasks, or cards across supported platforms. Allows listing issues within a project, finding a specific issue by its key, retrieving issue details (key, title, status, assignees, reporter, creation date), creating new issues with detailed attributes, updating existing issues, and deleting issues. Requires an adapter instance.
```ruby
adapter = ActiveProject.adapter(:jira)
# List issues in a project
issues = adapter.list_issues("ACME", max_results: 10)
# => [#, ...]
# Find a specific issue by key
issue = adapter.find_issue("ACME-123")
puts "#{issue.key}: #{issue.title}"
puts "Status: #{issue.status}" # => :open, :in_progress, :closed
puts "Assignees: #{issue.assignees.map(&:name).join(', ')}"
puts "Reporter: #{issue.reporter.name}"
puts "Created: #{issue.created_at}"
# Create a new issue
new_issue = adapter.create_issue("ACME", {
project: { key: "ACME" },
summary: "Implement dark mode feature",
issue_type: { name: "Task" },
description: "Add dark mode toggle to user settings",
assignee_id: "557058:abc123...",
due_on: Date.today + 7,
priority: { name: "High" }
})
# => #
# Update an issue
updated_issue = adapter.update_issue("ACME-456", {
summary: "[Updated] Implement dark mode feature",
description: "Add dark mode toggle with persistence"
})
# Delete an issue
adapter.delete_issue("ACME-456")
# => true
```
--------------------------------
### Access GitHub Platform-Specific Features
Source: https://context7.com/seuros/active_project/llms.txt
Demonstrates how to access GitHub-specific data, such as pull request details and merged status, by accessing the raw data of an issue object. Requires the issue object obtained from the GitHub adapter.
```ruby
# GitHub-specific: Access pull request data
github = ActiveProject.adapter(:github)
issue = github.find_issue("123") # Could be a PR
if issue.raw_data["pull_request"]
pr_url = issue.raw_data["pull_request"]["html_url"]
puts "This is a pull request: #{pr_url}"
puts "Merged: #{issue.raw_data['merged']}"
end
```
--------------------------------
### Handle API Errors with Unified Exception Hierarchy
Source: https://context7.com/seuros/active_project/llms.txt
Illustrates robust error handling for API interactions using a unified exception hierarchy. Catches specific errors like AuthenticationError, NotFoundError, ValidationError, RateLimitError, NotImplementedError, and general ApiError.
```ruby
adapter = ActiveProject.adapter(:jira)
begin
issue = adapter.find_issue("INVALID-KEY")
rescue ActiveProject::AuthenticationError => e
puts "Authentication failed: #{e.message}"
# Handle expired credentials, invalid tokens, 401/403 errors
rescue ActiveProject::NotFoundError => e
puts "Resource not found: #{e.message}"
# Handle 404 errors for missing projects, issues, comments
rescue ActiveProject::ValidationError => e
puts "Validation failed: #{e.message}"
puts "Field errors: #{e.errors.inspect}"
puts "Status code: #{e.status_code}"
puts "Response body: #{e.response_body}"
# Handle 400/422 validation errors with field-level details
rescue ActiveProject::RateLimitError => e
puts "Rate limit exceeded: #{e.message}"
# Handle 429 rate limit errors, implement backoff
rescue ActiveProject::ApiError => e
puts "API error: #{e.message}"
puts "Status: #{e.status_code}"
puts "Response: #{e.response_body}"
puts "Original error: #{e.original_error}"
# Handle general API errors (5xx, connection issues)
rescue ActiveProject::NotImplementedError => e
puts "Feature not supported: #{e.message}"
# Handle adapter-specific unsupported operations
end
```
--------------------------------
### ActiveProject Comments API - Manage Comments
Source: https://context7.com/seuros/active_project/llms.txt
Facilitates adding and managing comments on issues across supported platforms. Includes adding a new comment with body text to a specific issue, and retrieving comment details such as author, creation timestamp, and comment ID. Requires an adapter instance.
```ruby
adapter = ActiveProject.adapter(:jira)
# Add a comment to an issue
comment = adapter.add_comment("ACME-123", "This has been fixed in the latest release.")
# => #
puts "Comment by: #{comment.author.name}"
puts "Created at: #{comment.created_at}"
puts "Comment ID: #{comment.id}"
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.