plutonium 0.23.4 → 0.23.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/plutonium.css +2 -2
- data/config/initializers/sqlite_json_alias.rb +1 -1
- data/docs/.vitepress/config.ts +60 -19
- data/docs/guide/cursor-rules.md +75 -0
- data/docs/guide/deep-dive/authorization.md +189 -0
- data/docs/guide/{getting-started → deep-dive}/resources.md +137 -0
- data/docs/guide/getting-started/{installation.md → 01-installation.md} +0 -105
- data/docs/guide/index.md +28 -0
- data/docs/guide/introduction/02-core-concepts.md +440 -0
- data/docs/guide/tutorial/01-project-setup.md +75 -0
- data/docs/guide/tutorial/02-creating-a-feature-package.md +45 -0
- data/docs/guide/tutorial/03-defining-resources.md +90 -0
- data/docs/guide/tutorial/04-creating-a-portal.md +101 -0
- data/docs/guide/tutorial/05-customizing-the-ui.md +128 -0
- data/docs/guide/tutorial/06-adding-custom-actions.md +101 -0
- data/docs/guide/tutorial/07-implementing-authorization.md +90 -0
- data/docs/index.md +24 -31
- data/docs/modules/action.md +190 -0
- data/docs/modules/authentication.md +236 -0
- data/docs/modules/configuration.md +599 -0
- data/docs/modules/controller.md +398 -0
- data/docs/modules/core.md +316 -0
- data/docs/modules/definition.md +876 -0
- data/docs/modules/display.md +759 -0
- data/docs/modules/form.md +605 -0
- data/docs/modules/generator.md +288 -0
- data/docs/modules/index.md +167 -0
- data/docs/modules/interaction.md +470 -0
- data/docs/modules/package.md +151 -0
- data/docs/modules/policy.md +176 -0
- data/docs/modules/portal.md +710 -0
- data/docs/modules/query.md +287 -0
- data/docs/modules/resource_record.md +618 -0
- data/docs/modules/routing.md +641 -0
- data/docs/modules/table.md +293 -0
- data/docs/modules/ui.md +631 -0
- data/docs/public/plutonium.mdc +667 -0
- data/lib/generators/pu/core/assets/assets_generator.rb +0 -5
- data/lib/plutonium/ui/display/resource.rb +7 -2
- data/lib/plutonium/ui/table/resource.rb +8 -3
- data/lib/plutonium/version.rb +1 -1
- metadata +36 -9
- data/docs/guide/getting-started/authorization.md +0 -296
- data/docs/guide/getting-started/core-concepts.md +0 -432
- data/docs/guide/getting-started/index.md +0 -21
- data/docs/guide/tutorial.md +0 -401
- /data/docs/guide/{what-is-plutonium.md → introduction/01-what-is-plutonium.md} +0 -0
@@ -1,432 +0,0 @@
|
|
1
|
-
# Core Concepts
|
2
|
-
|
3
|
-
::: tip What you'll learn
|
4
|
-
- Understanding Plutonium's architecture and core abstractions
|
5
|
-
- How resources and packages work together
|
6
|
-
- How to organize your application effectively
|
7
|
-
- Best practices for building maintainable applications
|
8
|
-
:::
|
9
|
-
|
10
|
-
## Resources
|
11
|
-
|
12
|
-
Resources are the fundamental building blocks of a Plutonium application. They represent your business domain objects and their associated behavior.
|
13
|
-
|
14
|
-
### Anatomy of a Resource
|
15
|
-
|
16
|
-
A resource consists of several interconnected components:
|
17
|
-
|
18
|
-
```mermaid
|
19
|
-
graph TD
|
20
|
-
A[Resource] --> B[Model]
|
21
|
-
A --> C[Definition]
|
22
|
-
A --> D[Policy]
|
23
|
-
A --> G[Actions]
|
24
|
-
|
25
|
-
B --> H[Database Schema]
|
26
|
-
C --> I[Fields & UI Logic]
|
27
|
-
C --> F[QueryObject]
|
28
|
-
D --> J[Authorization]
|
29
|
-
F --> L[Querying & Filtering]
|
30
|
-
G --> M[User Operations]
|
31
|
-
```
|
32
|
-
|
33
|
-
::: details Complete Resource Example
|
34
|
-
|
35
|
-
::: code-group
|
36
|
-
```ruby [Model]
|
37
|
-
# app/models/user.rb
|
38
|
-
class User < ApplicationRecord
|
39
|
-
include Plutonium::Resource::Record
|
40
|
-
|
41
|
-
# Associations
|
42
|
-
has_many :posts
|
43
|
-
has_many :comments
|
44
|
-
belongs_to :organization
|
45
|
-
|
46
|
-
# Scopes
|
47
|
-
scope :active, -> { where(status: :active) }
|
48
|
-
|
49
|
-
# Validations
|
50
|
-
validates :name, presence: true
|
51
|
-
validates :email, presence: true, uniqueness: true
|
52
|
-
validates :role, presence: true, inclusion: {in: %w[admin user]}
|
53
|
-
|
54
|
-
def admin? = role == "admin"
|
55
|
-
end
|
56
|
-
```
|
57
|
-
|
58
|
-
```ruby [Definition]
|
59
|
-
# app/definitions/user_definition.rb
|
60
|
-
class UserDefinition < Plutonium::Resource::Definition
|
61
|
-
# Display configuration
|
62
|
-
field :name, as: :string
|
63
|
-
field :email, as: :email
|
64
|
-
|
65
|
-
# Search configuration
|
66
|
-
search do |scope, query|
|
67
|
-
scope.where("name LIKE :q OR email LIKE :q", q: "%#{query}%")
|
68
|
-
end
|
69
|
-
|
70
|
-
# Filters
|
71
|
-
filter :role, with: SelectFilter, choices: %w[admin user guest]
|
72
|
-
filter :status, with: SelectFilter, choices: %w[active inactive]
|
73
|
-
|
74
|
-
# Scopes
|
75
|
-
scope :active
|
76
|
-
|
77
|
-
scope :admins do
|
78
|
-
where(role: :admin)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Actions
|
82
|
-
action :deactivate,
|
83
|
-
interaction: DeactivateUser,
|
84
|
-
color: :warning,
|
85
|
-
icon: Phlex::TablerIcons::UserOff
|
86
|
-
|
87
|
-
# UI Customization
|
88
|
-
show_page_title "User Details"
|
89
|
-
show_page_description "View and manage user information"
|
90
|
-
end
|
91
|
-
```
|
92
|
-
|
93
|
-
```ruby [Policy]
|
94
|
-
# app/policies/user_policy.rb
|
95
|
-
class UserPolicy < Plutonium::Resource::Policy
|
96
|
-
# Basic permissions
|
97
|
-
def read?
|
98
|
-
true
|
99
|
-
end
|
100
|
-
|
101
|
-
def create?
|
102
|
-
user.admin?
|
103
|
-
end
|
104
|
-
|
105
|
-
def update?
|
106
|
-
user.admin? || record.id == user.id
|
107
|
-
end
|
108
|
-
|
109
|
-
def destroy?
|
110
|
-
user.admin? && record.id != user.id
|
111
|
-
end
|
112
|
-
|
113
|
-
# Action permissions
|
114
|
-
def deactivate?
|
115
|
-
user.admin? && record.status == :active && record.id != user.id
|
116
|
-
end
|
117
|
-
|
118
|
-
# Attribute permissions
|
119
|
-
def permitted_attributes_for_read
|
120
|
-
if user.admin?
|
121
|
-
%i[name email role status created_at updated_at]
|
122
|
-
else
|
123
|
-
%i[name email status]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def permitted_attributes_for_create
|
128
|
-
if user.admin?
|
129
|
-
%i[name email role status password]
|
130
|
-
else
|
131
|
-
%i[name email password]
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def permitted_attributes_for_update
|
136
|
-
if user.admin?
|
137
|
-
%i[name email role]
|
138
|
-
else
|
139
|
-
%i[name email]
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# Association permissions
|
144
|
-
def permitted_associations
|
145
|
-
%i[posts comments]
|
146
|
-
end
|
147
|
-
end
|
148
|
-
```
|
149
|
-
|
150
|
-
|
151
|
-
```ruby [Deactivate Interaction]
|
152
|
-
# app/interactions/user_interactions/deactivate.rb
|
153
|
-
module UserInteractions
|
154
|
-
class Deactivate < Plutonium::Resource::Interaction
|
155
|
-
# Define presentable metadata
|
156
|
-
presents label: "Deactivate User",
|
157
|
-
icon: Phlex::TablerIcons::UserOff,
|
158
|
-
description: "Deactivate user account"
|
159
|
-
|
160
|
-
# Define attributes
|
161
|
-
attribute :resource, class: User
|
162
|
-
attribute :reason, :string
|
163
|
-
|
164
|
-
# Validations
|
165
|
-
validates :resource, presence: true
|
166
|
-
validates :reason, presence: true
|
167
|
-
|
168
|
-
# Business logic
|
169
|
-
def execute
|
170
|
-
resource.transaction do
|
171
|
-
resource.status = :inactive
|
172
|
-
resource.deactivated_at = Time.current
|
173
|
-
resource.deactivation_reason = reason
|
174
|
-
|
175
|
-
if resource.save
|
176
|
-
succeed(resource)
|
177
|
-
.with_message("User was successfully deactivated")
|
178
|
-
.with_redirect_response(resource)
|
179
|
-
else
|
180
|
-
failed(resource.errors)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
```
|
187
|
-
:::
|
188
|
-
|
189
|
-
## Packages
|
190
|
-
|
191
|
-
Packages are the way Plutonium helps you modularize your application. They're built on top of Rails Engines but provide additional structure and conventions.
|
192
|
-
|
193
|
-
There are two main types:
|
194
|
-
|
195
|
-
### Feature Packages
|
196
|
-
|
197
|
-
|
198
|
-
Feature packages help you organize your application into logical, reusable modules.
|
199
|
-
They contain your business domain logic and resources. They're self-contained and independent.
|
200
|
-
|
201
|
-
::: tip Key Characteristics
|
202
|
-
- Domain Models
|
203
|
-
- Business Logic
|
204
|
-
- No Web Interface
|
205
|
-
- Reusable Components
|
206
|
-
:::
|
207
|
-
|
208
|
-
::: code-group
|
209
|
-
```ruby [Directory Structure]
|
210
|
-
packages/
|
211
|
-
└── blogging/
|
212
|
-
├── app/
|
213
|
-
│ ├── models/
|
214
|
-
│ │ └── blogging/
|
215
|
-
│ │ ├── post.rb
|
216
|
-
│ │ └── comment.rb
|
217
|
-
│ ├── definitions/
|
218
|
-
│ │ └── blogging/
|
219
|
-
│ │ ├── post_definition.rb
|
220
|
-
│ │ └── comment_definition.rb
|
221
|
-
│ ├── policies/
|
222
|
-
│ │ └── blogging/
|
223
|
-
│ │ ├── post_policy.rb
|
224
|
-
│ │ └── comment_policy.rb
|
225
|
-
│ └── interactions/
|
226
|
-
│ └── blogging/
|
227
|
-
│ └── post_interactions/
|
228
|
-
│ ├── publish.rb
|
229
|
-
│ └── archive.rb
|
230
|
-
├── config/
|
231
|
-
│ └── routes.rb
|
232
|
-
└── lib/
|
233
|
-
└── engine.rb
|
234
|
-
```
|
235
|
-
|
236
|
-
```ruby [Engine Configuration]
|
237
|
-
# packages/blogging/lib/engine.rb
|
238
|
-
module Blogging
|
239
|
-
class Engine < ::Rails::Engine
|
240
|
-
include Plutonium::Package::Engine
|
241
|
-
|
242
|
-
# Package configuration goes here
|
243
|
-
isolate_namespace Blogging
|
244
|
-
end
|
245
|
-
end
|
246
|
-
```
|
247
|
-
:::
|
248
|
-
|
249
|
-
### Portal Packages
|
250
|
-
|
251
|
-
Portal packages provide web interfaces and control how users interact with features.
|
252
|
-
|
253
|
-
::: tip Key Characteristics
|
254
|
-
- Web Interface
|
255
|
-
- Authentication
|
256
|
-
- Resource Access Control
|
257
|
-
- Feature Composition
|
258
|
-
:::
|
259
|
-
|
260
|
-
::: code-group
|
261
|
-
```ruby [Directory Structure]
|
262
|
-
packages/
|
263
|
-
└── admin_portal/
|
264
|
-
├── app/
|
265
|
-
│ ├── controllers/
|
266
|
-
│ │ └── admin_portal/
|
267
|
-
│ │ ├── concerns/
|
268
|
-
│ │ │ └── controller.rb
|
269
|
-
│ │ ├── plutonium_controller.rb
|
270
|
-
│ │ └── resource_controller.rb
|
271
|
-
│ └── views/
|
272
|
-
│ └── layouts/
|
273
|
-
│ └── admin_portal.html.erb
|
274
|
-
├── config/
|
275
|
-
│ └── routes.rb
|
276
|
-
└── lib/
|
277
|
-
└── engine.rb
|
278
|
-
```
|
279
|
-
|
280
|
-
```ruby [Engine Configuration]
|
281
|
-
# packages/admin_portal/lib/engine.rb
|
282
|
-
module AdminPortal
|
283
|
-
class Engine < ::Rails::Engine
|
284
|
-
include Plutonium::Portal::Engine
|
285
|
-
|
286
|
-
# Scope all resources to organization
|
287
|
-
scope_to_entity Organization, strategy: :path
|
288
|
-
end
|
289
|
-
end
|
290
|
-
```
|
291
|
-
|
292
|
-
```ruby [Routes Configuration]
|
293
|
-
# packages/admin_portal/config/routes.rb
|
294
|
-
AdminPortal::Engine.routes.draw do
|
295
|
-
root to: "dashboard#index"
|
296
|
-
|
297
|
-
# Register resources from feature packages
|
298
|
-
register_resource Blogging::Post
|
299
|
-
register_resource Blogging::Comment
|
300
|
-
end
|
301
|
-
```
|
302
|
-
|
303
|
-
```ruby [Controller Configuration]
|
304
|
-
# packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
|
305
|
-
module AdminPortal
|
306
|
-
module Concerns
|
307
|
-
class Controller < ::Rails::Engine
|
308
|
-
extend ActiveSupport::Concern
|
309
|
-
include Plutonium::Portal::Controller
|
310
|
-
# Integrate authentication
|
311
|
-
include Plutonium::Auth::Rodauth(:admin)
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
```
|
316
|
-
:::
|
317
|
-
|
318
|
-
## Entity Scoping
|
319
|
-
|
320
|
-
Entity scoping is a powerful feature that allows you to partition resources based on a parent entity (like Organization or Account).
|
321
|
-
It's how Plutonium achieve's multitenancy.
|
322
|
-
|
323
|
-
By properly defining associations to an entity, row-level multitenancy comes for free, out of the box.
|
324
|
-
|
325
|
-
```ruby
|
326
|
-
# Scope definition in engine
|
327
|
-
module AdminPortal
|
328
|
-
class Engine < ::Rails::Engine
|
329
|
-
include Plutonium::Portal::Engine
|
330
|
-
|
331
|
-
# Path-based scoping (/org_123/posts)
|
332
|
-
scope_to_entity Organization, strategy: :path
|
333
|
-
|
334
|
-
# Or custom scoping
|
335
|
-
scope_to_entity Organization, strategy: :current_organization
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
# Model implementation
|
340
|
-
class Post < ApplicationRecord
|
341
|
-
include Plutonium::Resource::Record
|
342
|
-
|
343
|
-
# Define a direct relationship to the entity
|
344
|
-
belongs_to :user
|
345
|
-
belongs_to :organization, through: :user
|
346
|
-
|
347
|
-
# Alternatively, if there's no direct relationship
|
348
|
-
scope :associated_with_organization, ->(organization) do
|
349
|
-
# custom scoping logic goes here
|
350
|
-
joins(:user).where(users: { organization_id: organization.id })
|
351
|
-
end
|
352
|
-
end
|
353
|
-
|
354
|
-
# Controller config
|
355
|
-
class ResourceController < PlutoniumController
|
356
|
-
include Plutonium::Resource::Controller
|
357
|
-
|
358
|
-
private
|
359
|
-
|
360
|
-
def current_organization
|
361
|
-
# Get tenant from the current subdomain
|
362
|
-
@current_organization ||= Organization.where(subdomain: request.subdomain).first!
|
363
|
-
end
|
364
|
-
end
|
365
|
-
```
|
366
|
-
|
367
|
-
## Best Practices
|
368
|
-
|
369
|
-
### Package Organization
|
370
|
-
|
371
|
-
::: tip Feature Packages
|
372
|
-
1. Keep domain logic isolated
|
373
|
-
2. Clear boundaries between features
|
374
|
-
3. Minimal dependencies between packages
|
375
|
-
4. Well-defined interfaces
|
376
|
-
:::
|
377
|
-
|
378
|
-
::: tip Portal Packages
|
379
|
-
1. Single responsibility (admin, customer)
|
380
|
-
2. Consistent authentication strategy
|
381
|
-
3. Clear resource scoping rules
|
382
|
-
4. Feature composition over duplication
|
383
|
-
:::
|
384
|
-
|
385
|
-
### Resource Design
|
386
|
-
|
387
|
-
::: tip Model Layer
|
388
|
-
1. Clear validations and constraints
|
389
|
-
2. Proper association setup
|
390
|
-
3. Meaningful scopes
|
391
|
-
:::
|
392
|
-
|
393
|
-
::: tip Definition Layer
|
394
|
-
1. Appropriate field types
|
395
|
-
2. Clear action definitions
|
396
|
-
3. Efficient search implementation
|
397
|
-
:::
|
398
|
-
|
399
|
-
::: tip Policy Layer
|
400
|
-
1. Granular permissions
|
401
|
-
2. Attribute-level access control
|
402
|
-
3. Action-specific rules
|
403
|
-
4. Association permissions
|
404
|
-
:::
|
405
|
-
|
406
|
-
### Security Considerations
|
407
|
-
|
408
|
-
::: warning Important
|
409
|
-
1. Always implement proper policies
|
410
|
-
2. Use entity scoping consistently
|
411
|
-
3. Validate all inputs
|
412
|
-
4. Control association access
|
413
|
-
5. Audit sensitive actions
|
414
|
-
:::
|
415
|
-
|
416
|
-
## Generator Support
|
417
|
-
|
418
|
-
Plutonium provides generators to quickly scaffold components:
|
419
|
-
|
420
|
-
```bash
|
421
|
-
# Create a new feature package
|
422
|
-
rails generate pu:pkg:package blogging
|
423
|
-
|
424
|
-
# Create a new portal package
|
425
|
-
rails generate pu:pkg:portal admin
|
426
|
-
|
427
|
-
# Create a new resource
|
428
|
-
rails generate pu:res:scaffold post title:string content:text
|
429
|
-
|
430
|
-
# Connect a resource to a portal
|
431
|
-
rails generate pu:res:conn
|
432
|
-
```
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# Getting Started with Plutonium
|
2
|
-
|
3
|
-
<!--
|
4
|
-
|
5
|
-
After reading this guide, you will know:
|
6
|
-
|
7
|
-
- How to install Plutonium.
|
8
|
-
- The general layout of a Plutonium application.
|
9
|
-
- The basic principles of Resource design.
|
10
|
-
- How to quickly generate the starting pieces of a Plutonium application.
|
11
|
-
-->
|
12
|
-
This guide covers getting up and running with Plutonium.
|
13
|
-
It is intended to be a more detailed guide.
|
14
|
-
|
15
|
-
If you're interested in a quick start, check out our [tutorial](/guide/tutorial).
|
16
|
-
|
17
|
-
## Prerequisites
|
18
|
-
|
19
|
-
Before using Plutonium, you should be familiar with Rails.
|
20
|
-
Plutonium builds upon many core Rails concepts and conventions.
|
21
|
-
If you're new to Rails or need a refresher, we highly recommend reading the [Rails' guide](https://guides.rubyonrails.org/getting_started.html).
|