
plutonium-controller
by radioactive-labs
Build production-ready Rails apps in minutes, not days. Convention-driven, fully customizable, AI-ready.
SKILL.md
name: plutonium-controller description: Plutonium resource controllers - CRUD actions, customization, and integration
Plutonium Controllers
Controllers in Plutonium provide full CRUD functionality out of the box. You rarely need to customize them - definitions handle most UI configuration and policies handle authorization.
Base Classes
# app/controllers/resource_controller.rb (generated during install)
class ResourceController < ApplicationController
include Plutonium::Resource::Controller
end
# app/controllers/posts_controller.rb (generated per resource)
class PostsController < ::ResourceController
# Empty - all CRUD actions inherited
end
What You Get for Free
Every resource controller automatically provides:
| Action | Route | Purpose |
|---|---|---|
index | GET /posts | List with pagination, search, filters, sorting |
show | GET /posts/:id | Display single record |
new | GET /posts/new | New record form |
create | POST /posts | Create record |
edit | GET /posts/:id/edit | Edit record form |
update | PATCH /posts/:id | Update record |
destroy | DELETE /posts/:id | Delete record |
Plus interactive action routes for custom operations defined in definitions.
When to Customize
Use Definitions for:
- Field configuration (inputs, displays, columns)
- Search, filters, scopes, sorting
- Actions (interactive operations)
- Form customization
Customize Controller for:
- Custom redirect logic
- Special parameter processing
- Non-standard authorization flows
- External integrations
- Response format changes
Override Hooks
All customization is done by overriding private methods:
Redirect Hooks
class PostsController < ::ResourceController
private
# Where to go after create/update: "show" (default), "edit", "new", "index"
def preferred_action_after_submit
"edit"
end
# Custom URL after create/update (overrides preferred_action_after_submit)
def redirect_url_after_submit
posts_path
end
# Custom URL after destroy
def redirect_url_after_destroy
posts_path
end
end
Parameter Hooks
class PostsController < ::ResourceController
private
# Modify params before create/update
def resource_params
params = super
params[:tags] = params[:tags].split(",") if params[:tags].is_a?(String)
params
end
end
Query Hooks
class PostsController < ::ResourceController
private
# Customize the index query
def filtered_resource_collection
base = current_authorized_scope
base = base.featured if params[:featured]
current_query_object.apply(base, raw_resource_query_params)
end
end
Presentation Hooks
Control whether parent/entity fields appear in forms and displays:
class PostsController < ::ResourceController
private
# Show parent field in displays (default: false)
def present_parent?
true
end
# Include parent field in forms (default: same as present_parent?)
def submit_parent?
true
end
# Show scoped entity in displays (default: false)
def present_scoped_entity?
true
end
# Include scoped entity in forms (default: same as present_scoped_entity?)
def submit_scoped_entity?
true
end
end
Custom Actions
class PostsController < ::ResourceController
def publish
authorize_current!(resource_record!, to: :publish?)
resource_record!.update!(published: true)
redirect_to resource_url_for(resource_record!), notice: "Published!"
end
end
Note: For most custom operations, use Interactive Actions in definitions instead.
Key Methods
Resource Access
resource_class # The model class (e.g., Post)
resource_record! # Current record (raises if not found)
resource_record? # Current record (nil if not found)
resource_params # Permitted params for create/update
current_parent # Parent record for nested routes
Authorization
authorize_current!(record, to: :action?) # Check permission
current_policy # Policy for current resource
permitted_attributes # Allowed attributes for action
current_authorized_scope # Scoped records user can access
Definition Access
current_definition # Definition for current resource
UI Building
build_form # Build form component
build_detail # Build show/detail component
build_collection # Build table component
URL Generation
resource_url_for(@post) # URL for record
resource_url_for(@post, action: :edit) # Edit URL
resource_url_for(Post) # Index URL
# With parent (nested resources)
resource_url_for(@comment, parent: @post) # Nested URL
resource_url_for(Comment, action: :new, parent: @post)
# Cross-package URLs
resource_url_for(@post, package: AdminPortal)
Nested Resources
Parent records are automatically resolved from routes with the nested_ prefix:
# Route: /users/:user_id/nested_posts/:id
class PostsController < ::ResourceController
# current_parent returns the User
# current_nested_association returns :posts
# resource_record! returns the Post scoped to that User
end
Key Methods for Nested Resources
current_parent # Parent record (e.g., User instance)
current_nested_association # Association name (e.g., :posts)
parent_route_param # URL param (e.g., :user_id)
parent_input_param # Form param (e.g., :user)
Parent fields are automatically excluded from forms/displays. Override with presentation hooks (see above).
has_one Support
For has_one associations, routes are singular:
/users/:user_id/nested_profile(no:idparam)- Index redirects to show (or new if no record exists)
Entity Scoping (Multi-tenancy)
When a portal is scoped to an entity:
# packages/admin_portal/lib/engine.rb
module AdminPortal
class Engine < Rails::Engine
include Plutonium::Portal::Engine
config.after_initialize do
scope_to_entity Organization, strategy: :path
end
end
end
Controllers automatically:
- Scope all queries to the entity
- Exclude entity field from forms
- Provide
current_scoped_entitymethod
Authorization Verification
Controllers verify authorization was performed:
# These run after every action
verify_authorize_current # Ensures authorize_current! was called
verify_current_authorized_scope # Ensures scope was loaded (except new/create)
To skip verification for custom actions:
class PostsController < ::ResourceController
skip_verify_authorize_current only: [:custom_action]
def custom_action
# Handle authorization manually
end
end
Response Formats
Controllers respond to multiple formats:
def show
# Responds to:
# - HTML (default)
# - JSON (via RABL templates)
# - Turbo Stream (for Hotwire)
end
Portal-Specific Controllers
Each portal can have its own controller override. Portal controllers inherit from the feature package's controller:
# packages/admin_portal/app/controllers/admin_portal/posts_controller.rb
class AdminPortal::PostsController < ::PostsController
include AdminPortal::Concerns::Controller
private
def preferred_action_after_submit
"index" # Admin prefers list view
end
end
Controllers are auto-created if not defined. When accessing a portal resource, Plutonium dynamically creates the controller by inheriting from the feature package's controller.
For non-resource portal pages (dashboard, settings), inherit from PlutoniumController:
module AdminPortal
class DashboardController < PlutoniumController
def index
# Dashboard home
end
end
end
Best Practices
- Keep controllers thin - Use definitions for UI, policies for auth, interactions for logic
- Don't override CRUD actions - Customize via hooks (
resource_params,redirect_url_after_submit) - Use interactive actions - For custom operations, define in definition with interaction
- Let authorization work - Don't skip verification without good reason
- Trust the framework - Most customization belongs in definitions or policies
Related Skills
plutonium-resource- How controllers fit in the resource architectureplutonium-policy- Authorization (used by controllers)plutonium-definition-actions- Interactive actions (preferred over custom controller actions)plutonium-views- Custom page, form, display, and table classesplutonium-nested-resources- Parent/child routes and scopingplutonium-model- Resource models
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon
