Packages
Plutonium apps are organized into packages — Rails engines with stricter conventions. Two flavors, hard split:
| Type | Purpose | Generator | Examples |
|---|---|---|---|
| Feature | Business logic (models, policies, definitions, interactions, migrations) | pu:pkg:package NAME | blogging, billing, inventory |
| Portal | Web interface (controllers, views, routes, auth) | pu:pkg:portal NAME | admin_portal, customer_portal, public_portal |
🚨 Critical
- Feature ↔ portal split is hard. Feature packages hold models/policies/definitions/interactions. Portal packages hold controllers/views/routes/auth. Don't mix.
- Package classes are auto-namespaced.
packages/blogging/app/models/blogging/post.rbresolves toBlogging::Post. Don't fight it. - Cross-package references use full namespace.
rails g pu:res:conn Blogging::Post --dest=admin_portal. - A resource is invisible until
pu:res:connregisters it with a portal.
Feature packages
rails g pu:pkg:package bloggingStructure
packages/blogging/
├── app/
│ ├── models/blogging/ # Blogging::Post
│ ├── definitions/blogging/ # Blogging::PostDefinition
│ ├── policies/blogging/ # Blogging::PostPolicy
│ └── interactions/blogging/ # Blogging::PublishPostInteraction
├── db/migrate/
└── lib/engine.rbEngine
module Blogging
class Engine < Rails::Engine
include Plutonium::Package::Engine
end
endAuto-namespacing
Every file under app/<kind>/blogging/ resolves to Blogging::*:
app/models/blogging/post.rb→Blogging::Postapp/policies/blogging/post_policy.rb→Blogging::PostPolicyapp/definitions/blogging/post_definition.rb→Blogging::PostDefinitionapp/interactions/blogging/publish_post_interaction.rb→Blogging::PublishPostInteraction
Each feature package gets its own base classes:
Blogging::ApplicationRecordBlogging::ResourceRecordBlogging::ResourcePolicyBlogging::ResourceDefinitionBlogging::ResourceInteraction
These inherit from the main app's base classes — extend them for package-wide defaults.
Creating resources inside a feature package
rails g pu:res:scaffold Blogging::Post title:string --dest=bloggingCross-package references use the full namespace:
rails g pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=commentsPortal packages
rails g pu:pkg:portal adminSee Portals for full details on portal generators, engine config, and routing. Key structural points here:
packages/admin_portal/
├── app/
│ ├── controllers/admin_portal/
│ │ ├── concerns/controller.rb # auth + shared filters
│ │ ├── dashboard_controller.rb
│ │ ├── plutonium_controller.rb
│ │ └── resource_controller.rb
│ ├── definitions/admin_portal/ # per-portal overrides
│ ├── policies/admin_portal/ # per-portal overrides
│ └── views/layouts/admin_portal.html.erb
├── config/routes.rb
└── lib/engine.rbPackage loading
config/packages.rb (created by pu:core:install):
Dir.glob(File.expand_path("../packages/**/lib/engine.rb", __dir__)) do |package|
load package
endThis is loaded from config/application.rb. Migrations from all packages are picked up by rails db:migrate automatically.
When to use which
Feature packages — domain logic that:
- Could be reused across multiple portals (admin and customer both edit
Blogging::Post). - Has no inherent UI / auth (it's just behavior).
- You want isolated from other domains (
billingshould not depend onblogging).
Portal packages — user-facing surfaces that:
- Have a specific auth flow (admin vs customer vs public).
- Render different views of the same underlying resources.
- Need different policies / definitions per audience.
Typical architecture
packages/
├── blogging/ # Feature: blog functionality
│ └── models, definitions, policies, interactions
├── billing/ # Feature: payments/invoicing
│ └── models, definitions, policies, interactions
├── admin_portal/ # Portal: admin interface
│ └── controllers, views, routes
└── customer_portal/ # Portal: customer dashboard
└── controllers, views, routesThe portals expose the features. A single feature can be exposed by multiple portals — usually with different policies and definitions per portal.
Related
- Portals — portal-specific configuration (mounting, auth, route registration)
- Generators —
pu:pkg:packageandpu:pkg:portalflags - Guide: Creating Packages — task-oriented walkthrough
