Adding Resources
Add a new model to your Plutonium app: scaffold it, migrate it, connect it to a portal.
Goal
Get a working list/show/new/edit/delete UI for a new model with sensible defaults, then customize as needed.
Steps
1. Scaffold the resource
rails g pu:res:scaffold Post user:belongs_to title:string 'content:text?' published:boolean --dest=main_appQuote any field containing ? or {} to prevent shell expansion.
Full field-type syntax: Reference › Resource › Model. For all pu:res:scaffold options: Reference › Generators.
2. Review the migration
Plutonium generates a basic migration. Before running it, edit db/migrate/<timestamp>_create_posts.rb to add:
- Cascade deletes (
foreign_key: {on_delete: :cascade}) - Composite indexes for tenant-scoped uniqueness
- Sensible defaults
3. Run the migration
rails db:prepare4. Connect to a portal
rails g pu:res:conn Post --dest=admin_portalThis creates the portal-specific controller, policy, and definition, plus registers the resource in the portal's routes. Until you do this, the resource has no URL.
Run it after the migration. When there is no base policy to inherit from, pu:res:conn seeds the policy's attribute lists from the table's columns; on an unmigrated table it logs an error and writes empty lists.
For singular resources (/profile, /settings), add --singular:
rails g pu:res:conn Profile --dest=customer_portal --singular5. Trim the generated policy
The generator is liberal: it seeds permitted_attributes_for_* from your model columns. Open packages/admin_portal/app/policies/admin_portal/post_policy.rb and:
- Drop
_idfields when the form should use the association name (e.g.:user, not:user_id). - Replace
:price_centswith:priceif the model useshas_cents. - Reduce to what users should actually be able to set/see.
See Reference › Behavior › Policies for details.
6. Visit the portal
http://localhost:3000/admin/postsYou should see:
- Index page with the columns auto-detected from your model.
- "New" button.
- Show / edit / delete on each row.
Customizing what you get
| Want to change | Edit | See |
|---|---|---|
| Which fields appear / how they render | The definition | Reference › Resource › Definition |
| Search, filters, scopes, sorting | The definition | Reference › Resource › Query |
| Custom buttons / bulk actions | The definition + an interaction | Reference › Resource › Actions |
| Authorization rules | The policy | Reference › Behavior › Policies |
| Redirects, params, presentation | The controller | Reference › Behavior › Controllers |
| Custom page layouts | The definition's nested page classes | Reference › UI › Pages |
Adding fields later
Two paths:
Migration only. Add a new column with a standard Rails migration. Plutonium auto-detects it and shows it in all CRUD pages.
Field with custom rendering. Add the column, then declare it in the definition:
# app/definitions/post_definition.rb
class PostDefinition < ResourceDefinition
input :slug, hint: "URL-friendly identifier"
endConverting an existing model
If the model already exists, skip the model generation:
# 1. Include the module
class Post < ApplicationRecord
include Plutonium::Resource::Record
end# 2. Scaffold the rest (skips model + migration)
rails g pu:res:scaffold Post --no-migration --dest=main_app
# 3. Connect to portal
rails g pu:res:conn Post --dest=admin_portalResources in feature packages
rails g pu:res:scaffold Blogging::Post title:string --dest=blogging
rails db:prepare
rails g pu:res:conn Blogging::Post --dest=admin_portalSee Creating packages for the package structure.
Cross-package references
rails g pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=commentsThe blogging/post syntax expands to Blogging::Post.
Related
- Reference › App › Generators: full generator catalog
- Reference › Resource: model + definition + query + actions
- Reference › App › Portals:
pu:res:conndetails - Creating packages: resources in feature packages
- Nested resources: parent/child relationships
