Skip to content

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 ​

bash
rails g pu:res:scaffold Post user:belongs_to title:string 'content:text?' published:boolean --dest=main_app

Quote 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 ​

bash
rails db:prepare

4. Connect to a portal ​

bash
rails g pu:res:conn Post --dest=admin_portal

This 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:

bash
rails g pu:res:conn Profile --dest=customer_portal --singular

5. 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 _id fields when the form should use the association name (e.g. :user, not :user_id).
  • Replace :price_cents with :price if the model uses has_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/posts

You 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 changeEditSee
Which fields appear / how they renderThe definitionReference › Resource › Definition
Search, filters, scopes, sortingThe definitionReference › Resource › Query
Custom buttons / bulk actionsThe definition + an interactionReference › Resource › Actions
Authorization rulesThe policyReference › Behavior › Policies
Redirects, params, presentationThe controllerReference › Behavior › Controllers
Custom page layoutsThe definition's nested page classesReference › 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:

ruby
# app/definitions/post_definition.rb
class PostDefinition < ResourceDefinition
  input :slug, hint: "URL-friendly identifier"
end

Converting an existing model ​

If the model already exists, skip the model generation:

ruby
# 1. Include the module
class Post < ApplicationRecord
  include Plutonium::Resource::Record
end
bash
# 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_portal

Resources in feature packages ​

bash
rails g pu:res:scaffold Blogging::Post title:string --dest=blogging
rails db:prepare
rails g pu:res:conn Blogging::Post --dest=admin_portal

See Creating packages for the package structure.

Cross-package references ​

bash
rails g pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=comments

The blogging/post syntax expands to Blogging::Post.

Released under the MIT License.