Skip to content

Packages โ€‹

Plutonium apps are organized into packages โ€” Rails engines with stricter conventions. Two flavors, hard split:

TypePurposeGeneratorExamples
FeatureBusiness logic (models, policies, definitions, interactions, migrations)pu:pkg:package NAMEblogging, billing, inventory
PortalWeb interface (controllers, views, routes, auth)pu:pkg:portal NAMEadmin_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.rb resolves to Blogging::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:conn registers it with a portal.

Feature packages โ€‹

bash
rails g pu:pkg:package blogging

Structure โ€‹

packages/blogging/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ models/blogging/             # Blogging::Post
โ”‚   โ”œโ”€โ”€ definitions/blogging/        # Blogging::PostDefinition
โ”‚   โ”œโ”€โ”€ policies/blogging/           # Blogging::PostPolicy
โ”‚   โ””โ”€โ”€ interactions/blogging/       # Blogging::PublishPostInteraction
โ”œโ”€โ”€ db/migrate/
โ””โ”€โ”€ lib/engine.rb

Engine โ€‹

ruby
module Blogging
  class Engine < Rails::Engine
    include Plutonium::Package::Engine
  end
end

Auto-namespacing โ€‹

Every file under app/<kind>/blogging/ resolves to Blogging::*:

  • app/models/blogging/post.rb โ†’ Blogging::Post
  • app/policies/blogging/post_policy.rb โ†’ Blogging::PostPolicy
  • app/definitions/blogging/post_definition.rb โ†’ Blogging::PostDefinition
  • app/interactions/blogging/publish_post_interaction.rb โ†’ Blogging::PublishPostInteraction

Each feature package gets its own base classes:

  • Blogging::ApplicationRecord
  • Blogging::ResourceRecord
  • Blogging::ResourcePolicy
  • Blogging::ResourceDefinition
  • Blogging::ResourceInteraction

These inherit from the main app's base classes โ€” extend them for package-wide defaults.

Creating resources inside a feature package โ€‹

bash
rails g pu:res:scaffold Blogging::Post title:string --dest=blogging

Cross-package references use the full namespace:

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

Portal packages โ€‹

bash
rails g pu:pkg:portal admin

See 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.rb

Package loading โ€‹

config/packages.rb (created by pu:core:install):

ruby
Dir.glob(File.expand_path("../packages/**/lib/engine.rb", __dir__)) do |package|
  load package
end

This 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 (billing should not depend on blogging).

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, routes

The portals expose the features. A single feature can be exposed by multiple portals โ€” usually with different policies and definitions per portal.

Released under the MIT License.