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
data/docs/guide/tutorial.md
DELETED
@@ -1,401 +0,0 @@
|
|
1
|
-
# Building a Blog with Plutonium
|
2
|
-
|
3
|
-
> **Quick Links:**
|
4
|
-
> - 🔍 [Tutorial Demo](https://github.com/radioactive-labs/plutonium-app)
|
5
|
-
> - 📂 [Tutorial Source Code](https://github.com/radioactive-labs/plutonium-app)
|
6
|
-
|
7
|
-
This tutorial walks through building a blog application using Plutonium. You'll learn how to:
|
8
|
-
|
9
|
-
- Set up authentication using Rodauth
|
10
|
-
- Create a blog feature package
|
11
|
-
- Build a dashboard/portal
|
12
|
-
- Implement posts and comments
|
13
|
-
- Add interactive actions
|
14
|
-
- Configure scoping and authorization
|
15
|
-
|
16
|
-
[Rest of the tutorial content remains exactly the same...]
|
17
|
-
|
18
|
-
## Initial Setup
|
19
|
-
|
20
|
-
Let's start by creating a new Rails application with Plutonium:
|
21
|
-
|
22
|
-
```bash
|
23
|
-
rails new plutonium_app -a propshaft -j esbuild -c tailwind \
|
24
|
-
-m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
|
25
|
-
```
|
26
|
-
|
27
|
-
This creates a new Rails application with:
|
28
|
-
- Propshaft as the asset pipeline
|
29
|
-
- esbuild for JavaScript bundling
|
30
|
-
- Tailwind CSS for styling
|
31
|
-
- Plutonium's base configuration
|
32
|
-
|
33
|
-
## Setting Up Authentication
|
34
|
-
|
35
|
-
Next, let's add authentication using Rodauth:
|
36
|
-
|
37
|
-
```bash
|
38
|
-
# Generate Rodauth configuration
|
39
|
-
rails generate pu:rodauth:install
|
40
|
-
|
41
|
-
# Generate user account setup
|
42
|
-
rails generate pu:rodauth:account user
|
43
|
-
rails db:migrate
|
44
|
-
```
|
45
|
-
|
46
|
-
This sets up:
|
47
|
-
- A User model with authentication
|
48
|
-
- Login/logout functionality
|
49
|
-
- Account verification via email
|
50
|
-
- Password reset capabilities
|
51
|
-
|
52
|
-

|
53
|
-
|
54
|
-
The key files created include:
|
55
|
-
- `app/models/user.rb` - The User model
|
56
|
-
- `app/rodauth/user_rodauth_plugin.rb` - Rodauth configuration
|
57
|
-
- `app/controllers/rodauth_controller.rb` - Base controller for auth pages
|
58
|
-
- Database migrations for users and auth-related tables
|
59
|
-
|
60
|
-
## Creating the Blog Feature Package
|
61
|
-
|
62
|
-
Let's create a dedicated package for our blogging functionality:
|
63
|
-
|
64
|
-
```bash
|
65
|
-
rails generate pu:pkg:package blogging
|
66
|
-
```
|
67
|
-
|
68
|
-
This generates a new feature package under `packages/blogging/` with:
|
69
|
-
- Base controllers
|
70
|
-
- Model and policy base classes
|
71
|
-
- Package-specific views directory
|
72
|
-
- Engine configuration
|
73
|
-
|
74
|
-
## Adding Posts Resource
|
75
|
-
|
76
|
-
Now we can add our first resource - blog posts:
|
77
|
-
|
78
|
-
```bash
|
79
|
-
rails generate pu:res:scaffold post user:belongs_to title:string \
|
80
|
-
content:text 'published_at:datetime?'
|
81
|
-
```
|
82
|
-
|
83
|
-
::: tip
|
84
|
-
Unlike Rails, Plutonium generates fields as non-null by default.
|
85
|
-
Appending `?` to the type e.g. `published_at:datetime?` makes `published_at` a **nullable** datetime.
|
86
|
-
:::
|
87
|
-
|
88
|
-
When prompted, select the `blogging` feature package.
|
89
|
-
|
90
|
-
This creates:
|
91
|
-
- Post model with associations
|
92
|
-
- Policy class with basic permissions
|
93
|
-
- Controllers for CRUD operations
|
94
|
-
- Database migration
|
95
|
-
|
96
|
-
The generated post model includes:
|
97
|
-
```ruby
|
98
|
-
class Blogging::Post < Blogging::ResourceRecord
|
99
|
-
belongs_to :user
|
100
|
-
validates :title, presence: true
|
101
|
-
validates :content, presence: true
|
102
|
-
end
|
103
|
-
```
|
104
|
-
|
105
|
-
Remember to apply the new migrations:
|
106
|
-
```bash
|
107
|
-
rails db:migrate
|
108
|
-
```
|
109
|
-
|
110
|
-
## Creating the Dashboard Portal
|
111
|
-
|
112
|
-
Let's add a portal to manage our blog:
|
113
|
-
|
114
|
-
```bash
|
115
|
-
rails generate pu:pkg:portal dashboard
|
116
|
-
```
|
117
|
-
|
118
|
-
When prompted, select `user` for authentication.
|
119
|
-
|
120
|
-
This creates a new portal package under `packages/dashboard_portal/` with:
|
121
|
-
- Portal-specific controllers
|
122
|
-
- Resource presentation layer
|
123
|
-
- Dashboard views
|
124
|
-
- Authenticated routes
|
125
|
-
|
126
|
-
## Configure Routes
|
127
|
-
|
128
|
-
Let's configure our application routes to properly handle authentication and dashboard access:
|
129
|
-
|
130
|
-
::: code-group
|
131
|
-
```ruby [app/rodauth/user_rodauth_plugin.rb]
|
132
|
-
# ==> Redirects
|
133
|
-
|
134
|
-
# Redirect to home after login.
|
135
|
-
create_account_redirect "/" # [!code --]
|
136
|
-
create_account_redirect "/dashboard" # [!code ++]
|
137
|
-
|
138
|
-
# Redirect to home after login.
|
139
|
-
login_redirect "/" # [!code --]
|
140
|
-
login_redirect "/dashboard" # [!code ++]
|
141
|
-
|
142
|
-
# Redirect to home page after logout.
|
143
|
-
logout_redirect "/" # [!code --]
|
144
|
-
logout_redirect "/dashboard" # [!code ++]
|
145
|
-
|
146
|
-
# Redirect to wherever login redirects to after account verification.
|
147
|
-
verify_account_redirect { login_redirect }
|
148
|
-
```
|
149
|
-
|
150
|
-
```ruby [config/routes.rb]
|
151
|
-
Rails.application.routes.draw do
|
152
|
-
# Other routes...
|
153
|
-
|
154
|
-
# Defines the root path route ("/")
|
155
|
-
# root "posts#index" # [!code --]
|
156
|
-
root to: redirect("/dashboard") # [!code ++]
|
157
|
-
end
|
158
|
-
```
|
159
|
-
:::
|
160
|
-
|
161
|
-
These changes ensure that:
|
162
|
-
- Users are directed to the dashboard after signing up
|
163
|
-
- Users are directed to the dashboard after logging in
|
164
|
-
- Users are directed to the dashboard after logging out
|
165
|
-
- The root URL (`/`) redirects to the dashboard
|
166
|
-
- Account verification follows the same flow as login
|
167
|
-
|
168
|
-
## Connecting Posts to Dashboard
|
169
|
-
|
170
|
-
We can now connect our blog posts to the dashboard:
|
171
|
-
|
172
|
-
```bash
|
173
|
-
rails generate pu:res:conn
|
174
|
-
```
|
175
|
-
|
176
|
-
Select:
|
177
|
-
1. Source feature: `blogging`
|
178
|
-
2. Resources: `Blogging::Post`
|
179
|
-
3. Portal: `dashboard_portal`
|
180
|
-
|
181
|
-
This configures the routing and controllers to display posts in the dashboard.
|
182
|
-
|
183
|
-

|
184
|
-
|
185
|
-
## Adding Comments
|
186
|
-
|
187
|
-
Let's add commenting functionality:
|
188
|
-
|
189
|
-
```bash
|
190
|
-
rails generate pu:res:scaffold comment blogging/post:belongs_to \
|
191
|
-
user:belongs_to body:text
|
192
|
-
|
193
|
-
rails db:migrate
|
194
|
-
|
195
|
-
rails generate pu:res:conn
|
196
|
-
```
|
197
|
-
|
198
|
-
::: tip
|
199
|
-
Note the use of the namespaced model in the association `blogging/post`.
|
200
|
-
|
201
|
-
Plutonium has inbuilt support for handling namespaces, generating:
|
202
|
-
```ruby
|
203
|
-
# model
|
204
|
-
belongs_to :post, class_name: "Blogging::Post"
|
205
|
-
|
206
|
-
# migration
|
207
|
-
t.belongs_to :post, null: false, foreign_key: {:to_table=>:blogging_posts}
|
208
|
-
```
|
209
|
-
:::
|
210
|
-
|
211
|
-
This creates:
|
212
|
-
- Comment model with associations
|
213
|
-
- Policy controlling access
|
214
|
-
- CRUD interface in dashboard
|
215
|
-
- Proper routing configuration
|
216
|
-
|
217
|
-
## Customizing the Interface
|
218
|
-
|
219
|
-
### Post Table Customization
|
220
|
-
|
221
|
-
We can customize how posts appear in the table view:
|
222
|
-
|
223
|
-
```ruby
|
224
|
-
# packages/blogging/app/policies/blogging/post_policy.rb
|
225
|
-
def permitted_attributes_for_index
|
226
|
-
[:user, :title, :published_at, :created_at]
|
227
|
-
end
|
228
|
-
```
|
229
|
-
|
230
|
-

|
231
|
-
|
232
|
-
### Post Detail View
|
233
|
-
|
234
|
-
Customize the post detail layout using display grids:
|
235
|
-
|
236
|
-
```ruby
|
237
|
-
# packages/blogging/app/definitions/blogging/post_definition.rb
|
238
|
-
class Blogging::PostDefinition < Blogging::ResourceDefinition
|
239
|
-
display :user, wrapper: {class: "col-span-full"}
|
240
|
-
display :title, wrapper: {class: "col-span-full"}
|
241
|
-
display :content, wrapper: {class: "col-span-full"}
|
242
|
-
display :published_at, wrapper: {class: "col-span-full"}
|
243
|
-
end
|
244
|
-
```
|
245
|
-
|
246
|
-

|
247
|
-
|
248
|
-
## Adding Publishing Functionality
|
249
|
-
|
250
|
-
Let's add the ability to publish posts:
|
251
|
-
|
252
|
-
::: code-group
|
253
|
-
|
254
|
-
```ruby [post_definition.rb]
|
255
|
-
# packages/blogging/app/definitions/blogging/post_definition.rb
|
256
|
-
action :publish,
|
257
|
-
interaction: Blogging::Posts::Publish,
|
258
|
-
collection_record_action: false # do not show this on the table
|
259
|
-
```
|
260
|
-
|
261
|
-
```ruby [publish.rb]
|
262
|
-
# packages/blogging/app/interactions/blogging/posts/publish.rb
|
263
|
-
module Blogging
|
264
|
-
module Posts
|
265
|
-
class Publish < ResourceInteraction
|
266
|
-
presents label: "Publish Post", icon: Phlex::TablerIcons::Send
|
267
|
-
attribute :resource
|
268
|
-
|
269
|
-
def execute
|
270
|
-
if resource.update(published_at: Time.current)
|
271
|
-
succeed(resource)
|
272
|
-
.with_message("Post was successfully published")
|
273
|
-
else
|
274
|
-
failed(resource.errors)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
```
|
281
|
-
|
282
|
-
```ruby [post_policy.rb]
|
283
|
-
# packages/blogging/app/policies/blogging/post_policy.rb
|
284
|
-
|
285
|
-
def publish? # [!code ++]
|
286
|
-
!record.published_at # [!code ++]
|
287
|
-
end # [!code ++]
|
288
|
-
|
289
|
-
|
290
|
-
def permitted_attributes_for_create
|
291
|
-
[:user, :title, :content, :published_at] # [!code --]
|
292
|
-
[:user, :title, :content] # [!code ++]
|
293
|
-
end
|
294
|
-
```
|
295
|
-
|
296
|
-
:::
|
297
|
-
|
298
|
-

|
299
|
-
|
300
|
-
## Adding Comments Panel
|
301
|
-
|
302
|
-
Enable viewing comments on posts:
|
303
|
-
|
304
|
-
::: code-group
|
305
|
-
|
306
|
-
```ruby [post.rb]
|
307
|
-
# packages/blogging/app/models/blogging/post.rb
|
308
|
-
has_many :comments
|
309
|
-
```
|
310
|
-
|
311
|
-
```ruby [post_policy.rb]
|
312
|
-
# packages/blogging/app/policies/blogging/post_policy.rb
|
313
|
-
def permitted_associations
|
314
|
-
%i[comments]
|
315
|
-
end
|
316
|
-
```
|
317
|
-
|
318
|
-
:::
|
319
|
-
|
320
|
-

|
321
|
-
|
322
|
-
## Scoping Resources
|
323
|
-
|
324
|
-
Ensure users only see their own content:
|
325
|
-
|
326
|
-
```ruby
|
327
|
-
# packages/dashboard_portal/lib/engine.rb
|
328
|
-
module DashboardPortal
|
329
|
-
class Engine < Rails::Engine
|
330
|
-
include Plutonium::Portal::Engine
|
331
|
-
|
332
|
-
config.after_initialize do
|
333
|
-
scope_to_entity User, strategy: :current_user
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
```
|
338
|
-
|
339
|
-
## Adding Nested Comments
|
340
|
-
|
341
|
-
Enable adding comments directly from the post form:
|
342
|
-
|
343
|
-
::: code-group
|
344
|
-
|
345
|
-
```ruby [post_definition.rb]
|
346
|
-
# packages/blogging/app/definitions/blogging/post_definition.rb
|
347
|
-
nested_input :comments,
|
348
|
-
using: Blogging::CommentDefinition,
|
349
|
-
fields: %i[user body]
|
350
|
-
```
|
351
|
-
|
352
|
-
```ruby [post.rb]
|
353
|
-
# packages/blogging/app/models/blogging/post.rb
|
354
|
-
has_many :comments
|
355
|
-
accepts_nested_attributes_for :comments # [!code ++]
|
356
|
-
```
|
357
|
-
|
358
|
-
```ruby [post_policy.rb]
|
359
|
-
# packages/blogging/app/policies/blogging/post_policy.rb
|
360
|
-
def permitted_attributes_for_create
|
361
|
-
[:user, :title, :content] # [!code --]
|
362
|
-
[:user, :title, :content, :comments] # [!code ++]
|
363
|
-
end
|
364
|
-
```
|
365
|
-
|
366
|
-
:::
|
367
|
-
|
368
|
-

|
369
|
-
|
370
|
-
## Running the Application
|
371
|
-
|
372
|
-
1. Start the Development server:
|
373
|
-
```bash
|
374
|
-
bin/dev
|
375
|
-
```
|
376
|
-
|
377
|
-
2. Visit `http://localhost:3000`
|
378
|
-
|
379
|
-
3. Create a user account and start managing your blog!
|
380
|
-
|
381
|
-
## What's Next?
|
382
|
-
|
383
|
-
Some ideas for extending the application:
|
384
|
-
- Add categories/tags for posts
|
385
|
-
- Implement comment moderation
|
386
|
-
- Add rich text editing for post content
|
387
|
-
- Create a public-facing blog view
|
388
|
-
- Add image attachments for posts
|
389
|
-
- Implement social sharing
|
390
|
-
|
391
|
-
## Conclusion
|
392
|
-
|
393
|
-
In this tutorial, we've built a full-featured blog application with:
|
394
|
-
- User authentication
|
395
|
-
- Post management
|
396
|
-
- Commenting system
|
397
|
-
- Publishing workflow
|
398
|
-
- Proper authorization
|
399
|
-
- User-scoped content
|
400
|
-
|
401
|
-
Plutonium helped us quickly scaffold and connect the pieces while maintaining clean separation of concerns through its package system.
|
File without changes
|