plutonium-create-resource
Generate Plutonium resources with models, migrations, controllers, policies, and definitions
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Create Resource Skill
Use the pu:res:scaffold generator to create complete resources in Plutonium applications.
Command Syntax
rails g pu:res:scaffold MODEL_NAME \
field1:type \
field2:type \
--dest=DESTINATION
IMPORTANT: Always specify --dest to avoid interactive prompts:
-
--dest=main_appfor resources in the main application -
--dest=package_namefor resources in a feature package
IMPORTANT: Quote fields containing ? or {} to prevent shell expansion:
'field:type?' # Nullable - must quote
'field:decimal{10,2}' # Options - must quote
'field:decimal?{10,2}' # Both - must quote
From Existing Models
For existing Rails projects with models you want to convert to Plutonium resources:
Option 1: Model already includes Plutonium::Resource::Record
rails g pu:res:scaffold Post --no-migration --dest=main_app
This generates only the definition, policy, and controller - leaving your model unchanged.
Option 2: Let the generator update the model
rails g pu:res:scaffold Post --dest=main_app
Run without attributes to auto-import fields from model.content_columns. This regenerates the model file, so review changes carefully.
Don't forget to include the module
Your model must include Plutonium::Resource::Record (directly or via inheritance):
class Post < ApplicationRecord
include Plutonium::Resource::Record
end
# Or inherit from a base class
class Post < ResourceRecord
end
Field Type Syntax
Format: name:type:index_type
Basic Types
| Syntax | Result |
|---|---|
name:string |
Required string |
'name:string?' |
Nullable string |
age:integer |
Required integer |
'age:integer?' |
Nullable integer |
active:boolean |
Required boolean |
'active:boolean?' |
Nullable boolean |
content:text |
Required text |
'content:text?' |
Nullable text |
birth_date:date |
Required date |
'anniversary:date?' |
Nullable date |
starts_at:datetime |
Required datetime |
'ends_at:datetime?' |
Nullable datetime |
alarm_time:time |
Required time |
'reminder_time:time?' |
Nullable time |
Decimal with Precision
The {precision,scale} syntax only works for decimal types:
'latitude:decimal{11,8}' # precision: 11, scale: 8
'amount:decimal{10,2}' # precision: 10, scale: 2
'latitude:decimal?{11,8}' # nullable with precision
Note: For default values on other types (boolean, integer, etc.), edit the migration manually.
References/Associations
company:belongs_to # Required foreign key
'parent:belongs_to?' # Nullable (null: true + optional: true)
user:references # Same as belongs_to
blogging/post:belongs_to # Cross-package reference
Nullable references generate:
- Migration:
null: true - Model:
belongs_to :parent, optional: true
Index Types (third segment)
email:string:index # Regular index
email:string:uniq # Unique index
Special Types
password_digest # has_secure_password
auth_token:token # has_secure_token (auto unique index)
content:rich_text # has_rich_text
avatar:attachment # has_one_attached
photos:attachments # has_many_attached
price_cents:integer # has_cents (money field)
Token fields automatically get a unique index in the migration.
Generator Options
-
--dest=DESTINATION- Target destination (always required to avoid prompts)-
main_appfor main application resources -
package_namefor feature package resources
-
-
--no-model- Skip model generation (keeps existing model) -
--no-migration- Skip migration generation (use with--no-modelfor existing models)
What Gets Generated
For main_app resources:
-
Model -
app/models/model_name.rb -
Migration -
db/migrate/xxx_create_model_names.rb -
Controller -
app/controllers/model_names_controller.rb -
Policy -
app/policies/model_name_policy.rb -
Definition -
app/definitions/model_name_definition.rb
For packaged resources:
-
Model -
app/models/package_name/model_name.rb -
Migration -
db/migrate/xxx_create_package_name_model_names.rb -
Controller -
packages/package_name/app/controllers/package_name/model_names_controller.rb -
Policy -
packages/package_name/app/policies/package_name/model_name_policy.rb -
Definition -
packages/package_name/app/definitions/package_name/model_name_definition.rb
Migration Customizations
The generator creates basic migrations. Always review and customize the migration before running:
Inline Indexes (preferred)
create_table :model_names do |t|
t.belongs_to :parent, null: false, foreign_key: true
t.string :name, null: false
t.timestamps
t.index :name
t.index [:parent_id, :name], unique: true
end
Cascade Delete
t.belongs_to :parent, null: false, foreign_key: {on_delete: :cascade}
Default Values
t.boolean :is_active, default: true
t.integer :status, default: 0
t.integer :count, null: true, default: 0
Examples
Main App Resource
rails g pu:res:scaffold Post \
user:belongs_to \
title:string \
'content:text?' \
'published_at:datetime?' \
--dest=main_app
Resource with Precision and Indexes
rails g pu:res:scaffold Property \
company:belongs_to \
code:string:uniq \
'latitude:decimal{11,8}' \
'longitude:decimal?{11,8}' \
'value:decimal?{15,2}' \
'notes:text?' \
--dest=main_app
Optional Association
rails g pu:res:scaffold Comment \
user:belongs_to \
'parent:belongs_to?' \
body:text \
--dest=blogging
Cross-Package Reference
rails g pu:res:scaffold Comment \
user:belongs_to \
blogging/post:belongs_to \
body:text \
--dest=comments
After Generation
- Review and customize the migration (add cascade delete, defaults, composite indexes)
- Run
rails db:migrate - Connect resource to portal:
rails g pu:res:conn Post --dest=admin_portal - Customize policy permissions as needed
- Add definition customizations for UI behavior
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!