plutonium 0.50.0 → 0.51.0

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.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +572 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +163 -300
  5. data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
  6. data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
  7. data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +6 -5
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +27 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1009 -1214
  14. data/app/assets/plutonium.js.map +3 -3
  15. data/app/assets/plutonium.min.js +52 -51
  16. data/app/assets/plutonium.min.js.map +3 -3
  17. data/docs/.vitepress/config.ts +37 -27
  18. data/docs/getting-started/index.md +22 -29
  19. data/docs/getting-started/installation.md +37 -80
  20. data/docs/getting-started/tutorial/index.md +4 -5
  21. data/docs/guides/adding-resources.md +66 -377
  22. data/docs/guides/authentication.md +94 -463
  23. data/docs/guides/authorization.md +124 -370
  24. data/docs/guides/creating-packages.md +94 -296
  25. data/docs/guides/custom-actions.md +121 -441
  26. data/docs/guides/index.md +22 -42
  27. data/docs/guides/multi-tenancy.md +116 -187
  28. data/docs/guides/nested-resources.md +103 -431
  29. data/docs/guides/search-filtering.md +123 -240
  30. data/docs/guides/testing.md +5 -4
  31. data/docs/guides/theming.md +157 -407
  32. data/docs/guides/troubleshooting.md +5 -3
  33. data/docs/guides/user-invites.md +106 -425
  34. data/docs/guides/user-profile.md +76 -243
  35. data/docs/index.md +1 -1
  36. data/docs/reference/app/generators.md +517 -0
  37. data/docs/reference/app/index.md +158 -0
  38. data/docs/reference/app/packages.md +146 -0
  39. data/docs/reference/app/portals.md +377 -0
  40. data/docs/reference/auth/accounts.md +230 -0
  41. data/docs/reference/auth/index.md +88 -0
  42. data/docs/reference/auth/profile.md +185 -0
  43. data/docs/reference/behavior/controllers.md +395 -0
  44. data/docs/reference/behavior/index.md +22 -0
  45. data/docs/reference/behavior/interactions.md +341 -0
  46. data/docs/reference/behavior/policies.md +417 -0
  47. data/docs/reference/index.md +56 -49
  48. data/docs/reference/resource/actions.md +423 -0
  49. data/docs/reference/resource/definition.md +508 -0
  50. data/docs/reference/resource/index.md +50 -0
  51. data/docs/reference/resource/model.md +348 -0
  52. data/docs/reference/resource/query.md +305 -0
  53. data/docs/reference/tenancy/entity-scoping.md +361 -0
  54. data/docs/reference/tenancy/index.md +36 -0
  55. data/docs/reference/tenancy/invites.md +393 -0
  56. data/docs/reference/tenancy/nested-resources.md +267 -0
  57. data/docs/reference/testing/index.md +287 -0
  58. data/docs/reference/ui/assets.md +400 -0
  59. data/docs/reference/ui/components.md +165 -0
  60. data/docs/reference/ui/displays.md +104 -0
  61. data/docs/reference/ui/forms.md +284 -0
  62. data/docs/reference/ui/index.md +30 -0
  63. data/docs/reference/ui/layouts.md +106 -0
  64. data/docs/reference/ui/pages.md +189 -0
  65. data/docs/reference/ui/tables.md +117 -0
  66. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  67. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  68. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  69. data/gemfiles/rails_7.gemfile.lock +1 -1
  70. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  71. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  72. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  73. data/lib/generators/pu/invites/install_generator.rb +1 -0
  74. data/lib/plutonium/definition/base.rb +1 -1
  75. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  76. data/lib/plutonium/helpers/turbo_helper.rb +11 -0
  77. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  78. data/lib/plutonium/resource/controller.rb +1 -0
  79. data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
  80. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  81. data/lib/plutonium/resource/policy.rb +7 -0
  82. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  83. data/lib/plutonium/ui/component/methods.rb +4 -0
  84. data/lib/plutonium/ui/form/base.rb +6 -2
  85. data/lib/plutonium/ui/form/components/json.rb +58 -0
  86. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  87. data/lib/plutonium/ui/form/components/secure_association.rb +98 -22
  88. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  89. data/lib/plutonium/ui/form/resource.rb +0 -4
  90. data/lib/plutonium/ui/grid/resource.rb +1 -1
  91. data/lib/plutonium/ui/layout/base.rb +1 -0
  92. data/lib/plutonium/ui/page/base.rb +0 -7
  93. data/lib/plutonium/ui/page/index.rb +4 -4
  94. data/lib/plutonium/ui/table/resource.rb +1 -1
  95. data/lib/plutonium/version.rb +1 -1
  96. data/lib/plutonium.rb +8 -0
  97. data/lib/tasks/release.rake +15 -1
  98. data/package.json +10 -10
  99. data/src/css/slim_select.css +4 -0
  100. data/src/js/controllers/slim_select_controller.js +61 -0
  101. data/src/js/turbo/turbo_actions.js +33 -0
  102. data/yarn.lock +553 -543
  103. metadata +44 -33
  104. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  105. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  106. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  107. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  108. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  109. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  110. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  111. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  112. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  113. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  114. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  115. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  116. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  117. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  118. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  119. data/docs/reference/assets/index.md +0 -496
  120. data/docs/reference/controller/index.md +0 -412
  121. data/docs/reference/definition/actions.md +0 -462
  122. data/docs/reference/definition/fields.md +0 -383
  123. data/docs/reference/definition/index.md +0 -326
  124. data/docs/reference/definition/query.md +0 -351
  125. data/docs/reference/generators/index.md +0 -648
  126. data/docs/reference/interaction/index.md +0 -449
  127. data/docs/reference/model/features.md +0 -248
  128. data/docs/reference/model/index.md +0 -218
  129. data/docs/reference/policy/index.md +0 -456
  130. data/docs/reference/portal/index.md +0 -379
  131. data/docs/reference/views/forms.md +0 -411
  132. data/docs/reference/views/index.md +0 -544
@@ -1,450 +1,139 @@
1
1
  # Adding Resources
2
2
 
3
- This guide covers creating new resources and connecting them to portals.
3
+ Add a new model to your Plutonium app: scaffold it, migrate it, connect it to a portal.
4
4
 
5
- ## Quick Start
5
+ ## Goal
6
6
 
7
- ```bash
8
- # Generate a resource in the main app
9
- rails g pu:res:scaffold Product name:string 'price:decimal{10,2}' --dest=main_app
10
-
11
- # Generate a resource in a feature package
12
- rails g pu:res:scaffold Product name:string 'price:decimal{10,2}' --dest=inventory
13
-
14
- # Connect to a portal
15
- rails g pu:res:conn Product --dest=admin_portal
16
- ```
17
-
18
- ## The Resource Generator
19
-
20
- ### Basic Usage
21
-
22
- ```bash
23
- rails g pu:res:scaffold ModelName field:type field:type --dest=DESTINATION
24
- ```
25
-
26
- **Always specify `--dest`** to avoid interactive prompts:
27
- - `--dest=main_app` for resources in the main application
28
- - `--dest=package_name` for resources in a feature package
29
-
30
- ### Field Types
31
-
32
- Format: `name:type:index_type`
33
-
34
- | Type | Example | Description |
35
- |------|---------|-------------|
36
- | `string` | `title:string` | Short text (required) |
37
- | `'title:string?'` | `'title:string?'` | Short text (nullable) |
38
- | `text` | `body:text` | Long text |
39
- | `integer` | `quantity:integer` | Whole numbers |
40
- | `decimal` | `'price:decimal{10,2}'` | Decimal with precision |
41
- | `float` | `rating:float` | Floating point |
42
- | `boolean` | `active:boolean` | True/false |
43
- | `date` | `published_on:date` | Date only |
44
- | `datetime` | `published_at:datetime` | Date and time |
45
- | `time` | `starts_at:time` | Time only |
46
- | `json` | `metadata:json` | JSON data |
47
- | `jsonb` | `settings:jsonb` | JSONB (PostgreSQL) |
48
- | `uuid` | `external_id:uuid` | UUID field |
49
-
50
- ### Nullable Fields
51
-
52
- Append `?` to make a field nullable. **Quote fields with special characters**:
53
-
54
- ```bash
55
- 'name:string?' # Nullable string
56
- 'description:text?' # Nullable text
57
- 'published_at:datetime?' # Nullable datetime
58
- ```
59
-
60
- ### Decimal Precision
7
+ Get a working list/show/new/edit/delete UI for a new model with sensible defaults, then customize as needed.
61
8
 
62
- Use `{precision,scale}` syntax for decimal fields:
9
+ ## Steps
63
10
 
64
- ```bash
65
- 'price:decimal{10,2}' # precision: 10, scale: 2
66
- 'latitude:decimal{11,8}' # precision: 11, scale: 8
67
- 'amount:decimal?{15,2}' # nullable with precision
68
- ```
69
-
70
- ### Default Values
71
-
72
- Use `{default:value}` syntax to set default values:
11
+ ### 1. Scaffold the resource
73
12
 
74
13
  ```bash
75
- 'status:string{default:draft}' # String default
76
- 'active:boolean{default:true}' # Boolean default
77
- 'priority:integer{default:0}' # Integer default
78
- 'price:decimal{10,2,default:0}' # Decimal with precision and default
79
- 'category:string?{default:general}' # Nullable with default
14
+ rails g pu:res:scaffold Post user:belongs_to title:string 'content:text?' published:boolean --dest=main_app
80
15
  ```
81
16
 
82
- ### Associations
83
-
84
- ```bash
85
- # Required belongs_to
86
- user:belongs_to
87
- company:references # Same as belongs_to
17
+ Quote any field containing `?` or `{}` to prevent shell expansion.
88
18
 
89
- # Nullable belongs_to
90
- 'parent:belongs_to?' # Creates: null: true, optional: true
19
+ Full field-type syntax: [Reference › Resource › Model](/reference/resource/model). For all `pu:res:scaffold` options: [Reference › Generators](/reference/app/generators#pu-res-scaffold).
91
20
 
92
- # Custom class_name (column author_id -> User model)
93
- 'author:belongs_to{class_name:User}'
94
- 'reviewer:belongs_to?{class_name:User}' # Nullable
21
+ ### 2. Review the migration
95
22
 
96
- # Cross-package reference
97
- blogging/post:belongs_to
98
- ```
23
+ Plutonium generates a basic migration. Before running it, edit `db/migrate/<timestamp>_create_posts.rb` to add:
99
24
 
100
- ### Indexes
25
+ - Cascade deletes (`foreign_key: {on_delete: :cascade}`)
26
+ - Composite indexes for tenant-scoped uniqueness
27
+ - Sensible defaults
101
28
 
102
- Add index type as the third segment:
29
+ ### 3. Run the migration
103
30
 
104
31
  ```bash
105
- email:string:index # Regular index
106
- email:string:uniq # Unique index
107
- ```
108
-
109
- ### Special Types
110
-
111
- ```bash
112
- password_digest # has_secure_password
113
- auth_token:token # has_secure_token (auto unique index)
114
- content:rich_text # has_rich_text (Action Text)
115
- avatar:attachment # has_one_attached (Active Storage)
116
- photos:attachments # has_many_attached
117
- price_cents:integer # has_cents (money field)
118
- ```
119
-
120
- ### Generator Options
121
-
122
- ```bash
123
- # Skip model generation (use existing model)
124
- rails g pu:res:scaffold Post --no-model --dest=main_app
125
-
126
- # Skip migration generation
127
- rails g pu:res:scaffold Post --no-migration --dest=main_app
128
-
129
- # Both (for existing models with Plutonium::Resource::Record)
130
- rails g pu:res:scaffold Post --no-model --no-migration --dest=main_app
131
- ```
132
-
133
- ## Generated Files
134
-
135
- ### For Main App Resources
136
-
137
- ```
138
- app/
139
- ├── models/post.rb
140
- ├── controllers/posts_controller.rb
141
- ├── definitions/post_definition.rb
142
- └── policies/post_policy.rb
143
- db/migrate/xxx_create_posts.rb
144
- ```
145
-
146
- ### For Packaged Resources
147
-
148
- ```
149
- packages/blogging/
150
- ├── app/
151
- │ ├── models/blogging/post.rb
152
- │ ├── controllers/blogging/posts_controller.rb
153
- │ ├── definitions/blogging/post_definition.rb
154
- │ └── policies/blogging/post_policy.rb
155
- db/migrate/xxx_create_blogging_posts.rb
156
- ```
157
-
158
- ### Model
159
-
160
- ```ruby
161
- class Post < ResourceRecord
162
- include Plutonium::Resource::Record
163
- end
164
- ```
165
-
166
- ### Definition
167
-
168
- ```ruby
169
- class PostDefinition < ResourceDefinition
170
- # Fields auto-detected from model
171
- end
172
- ```
173
-
174
- ### Policy
175
-
176
- ```ruby
177
- class PostPolicy < ResourcePolicy
178
- def permitted_attributes_for_create
179
- %i[title content user_id]
180
- end
181
-
182
- def permitted_attributes_for_read
183
- %i[title content user_id created_at updated_at]
184
- end
185
- end
32
+ rails db:migrate
186
33
  ```
187
34
 
188
- ## Connecting to Portals
189
-
190
- Resources must be connected to a portal to be accessible via the web.
191
-
192
- ### Using the Generator
35
+ ### 4. Connect to a portal
193
36
 
194
37
  ```bash
195
38
  rails g pu:res:conn Post --dest=admin_portal
196
39
  ```
197
40
 
198
- This:
199
- 1. Registers the resource in portal routes
200
- 2. Creates a portal-specific controller
201
- 3. Creates portal-specific policy and definition (if base versions don't exist)
41
+ This creates the portal-specific controller, policy, and definition, plus registers the resource in the portal's routes. Until you do this, the resource has no URL.
202
42
 
203
- ### Connecting Multiple Resources
43
+ For singular resources (`/profile`, `/settings`), add `--singular`:
204
44
 
205
45
  ```bash
206
- rails g pu:res:conn Post Comment Tag --dest=admin_portal
207
- ```
208
-
209
- ### Connecting Namespaced Resources
210
-
211
- Use the full class name for packaged resources:
212
-
213
- ```bash
214
- rails g pu:res:conn Blogging::Post Blogging::Comment --dest=admin_portal
46
+ rails g pu:res:conn Profile --dest=customer_portal --singular
215
47
  ```
216
48
 
217
- ### Connecting Singular Resources
49
+ ### 5. Trim the generated policy
218
50
 
219
- For resources that represent a single record per user (e.g., profile):
51
+ The generator is liberal it seeds `permitted_attributes_for_*` from your model columns. Open `packages/admin_portal/app/policies/admin_portal/post_policy.rb` and:
220
52
 
221
- ```bash
222
- rails g pu:res:conn Profile --dest=customer_portal --singular
223
- ```
53
+ - Drop `_id` fields when the form should use the association name (e.g. `:user`, not `:user_id`).
54
+ - Replace `:price_cents` with `:price` if the model uses `has_cents`.
55
+ - Reduce to what users should actually be able to set/see.
224
56
 
225
- This registers the resource with `singular: true`, generating routes like `/profile` instead of `/profiles/:id`.
57
+ See [Reference Behavior Policies](/reference/behavior/policies) for details.
226
58
 
227
- ### What Gets Generated
59
+ ### 6. Visit the portal
228
60
 
229
61
  ```
230
- packages/admin_portal/
231
- ├── app/
232
- │ ├── controllers/admin_portal/posts_controller.rb
233
- │ ├── policies/admin_portal/post_policy.rb
234
- │ └── definitions/admin_portal/post_definition.rb
235
- └── config/routes.rb # Updated with register_resource
62
+ http://localhost:3000/admin/posts
236
63
  ```
237
64
 
238
- ## Portal-Specific Customization
65
+ You should see:
239
66
 
240
- ### Portal Controller
67
+ - Index page with the columns auto-detected from your model.
68
+ - "New" button.
69
+ - Show / edit / delete on each row.
241
70
 
242
- ```ruby
243
- # packages/admin_portal/app/controllers/admin_portal/posts_controller.rb
244
- class AdminPortal::PostsController < ::PostsController
245
- include AdminPortal::Concerns::Controller
71
+ ## Customizing what you get
246
72
 
247
- private
73
+ | Want to change | Edit | See |
74
+ |---|---|---|
75
+ | Which fields appear / how they render | The definition | [Reference › Resource › Definition](/reference/resource/definition) |
76
+ | Search, filters, scopes, sorting | The definition | [Reference › Resource › Query](/reference/resource/query) |
77
+ | Custom buttons / bulk actions | The definition + an interaction | [Reference › Resource › Actions](/reference/resource/actions) |
78
+ | Authorization rules | The policy | [Reference › Behavior › Policies](/reference/behavior/policies) |
79
+ | Redirects, params, presentation | The controller | [Reference › Behavior › Controllers](/reference/behavior/controllers) |
80
+ | Custom page layouts | The definition's nested page classes | [Reference › UI › Pages](/reference/ui/pages) |
248
81
 
249
- def build_resource
250
- super.tap do |post|
251
- post.user = current_user
252
- end
253
- end
254
- end
255
- ```
82
+ ## Adding fields later
256
83
 
257
- ### Portal Definition
258
-
259
- ```ruby
260
- # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
261
- class AdminPortal::PostDefinition < ::PostDefinition
262
- # Add admin-only fields
263
- field :internal_notes
84
+ Two paths:
264
85
 
265
- # Customize existing fields
266
- field :status, as: :select, collection: %w[draft published archived]
267
- end
268
- ```
86
+ **Migration only.** Add a new column with a standard Rails migration. Plutonium auto-detects it — appears in all CRUD pages.
269
87
 
270
- ### Portal Policy
88
+ **Field with custom rendering.** Add the column, then declare it in the definition:
271
89
 
272
90
  ```ruby
273
- # packages/admin_portal/app/policies/admin_portal/post_policy.rb
274
- class AdminPortal::PostPolicy < ::PostPolicy
275
- include AdminPortal::ResourcePolicy
276
-
277
- # Admins can do everything
278
- def destroy?
279
- true
280
- end
281
-
282
- def permitted_attributes_for_create
283
- super + [:internal_notes]
284
- end
91
+ # app/definitions/post_definition.rb
92
+ class PostDefinition < ResourceDefinition
93
+ input :slug, hint: "URL-friendly identifier"
285
94
  end
286
95
  ```
287
96
 
288
- ## Multiple Portals
289
-
290
- Connect the same resource to multiple portals:
291
-
292
- ```bash
293
- rails g pu:res:conn Post --dest=admin_portal
294
- rails g pu:res:conn Post --dest=author_portal
295
- ```
296
-
297
- Each portal can have different customizations.
298
-
299
- ## From Existing Models
300
-
301
- If you have existing Rails models you want to convert to Plutonium resources:
302
-
303
- ### Option 1: Model already includes Plutonium::Resource::Record
304
-
305
- ```bash
306
- rails g pu:res:scaffold Post --no-model --no-migration --dest=main_app
307
- ```
308
-
309
- This generates only the definition, policy, and controller.
310
-
311
- ### Option 2: Let the generator update the model
312
-
313
- ```bash
314
- rails g pu:res:scaffold Post --dest=main_app
315
- ```
316
-
317
- Run without attributes to auto-import fields from the model's content columns.
318
-
319
- ### Required Model Setup
97
+ ## Converting an existing model
320
98
 
321
- Your model must include `Plutonium::Resource::Record`:
99
+ If the model already exists, skip the model generation:
322
100
 
323
101
  ```ruby
102
+ # 1. Include the module
324
103
  class Post < ApplicationRecord
325
104
  include Plutonium::Resource::Record
326
105
  end
327
106
  ```
328
107
 
329
- ## Adding Fields After Creation
330
-
331
- ### 1. Create Migration
332
-
333
108
  ```bash
334
- rails g migration AddStatusToPosts status:string
335
- ```
336
-
337
- ### 2. Update Model (if needed)
338
-
339
- ```ruby
340
- class Post < ResourceRecord
341
- validates :status, inclusion: { in: %w[draft published] }
342
- end
343
- ```
344
-
345
- ### 3. Fields Auto-Detected
346
-
347
- New columns automatically appear in forms. To customize:
348
-
349
- ```ruby
350
- # In definition
351
- field :status, as: :select, collection: %w[draft published]
352
- ```
353
-
354
- ## Migration Customizations
355
-
356
- Always review and customize generated migrations:
357
-
358
- ### Inline Indexes (preferred)
359
-
360
- ```ruby
361
- create_table :posts do |t|
362
- t.belongs_to :user, null: false, foreign_key: true
363
- t.string :title, null: false
364
-
365
- t.timestamps
366
-
367
- t.index :title
368
- t.index [:user_id, :title], unique: true
369
- end
370
- ```
371
-
372
- ### Cascade Delete
373
-
374
- ```ruby
375
- t.belongs_to :user, null: false, foreign_key: {on_delete: :cascade}
376
- ```
377
-
378
- ### Default Values
379
-
380
- Default values can be set directly in the generator using `{default:value}` syntax. For expressions or complex defaults, edit the migration:
109
+ # 2. Scaffold the rest (skips model + migration)
110
+ rails g pu:res:scaffold Post --no-migration --dest=main_app
381
111
 
382
- ```ruby
383
- t.boolean :is_active, default: true
384
- t.datetime :published_at, default: -> { "CURRENT_TIMESTAMP" }
112
+ # 3. Connect to portal
113
+ rails g pu:res:conn Post --dest=admin_portal
385
114
  ```
386
115
 
387
- ## Removing Resources
388
-
389
- ### Remove from Portal
390
-
391
- 1. Remove `register_resource` from portal routes
392
- 2. Delete portal-specific files in `packages/portal_name/app/`
393
-
394
- ### Remove Entirely
116
+ ## Resources in feature packages
395
117
 
396
118
  ```bash
397
- # Remove files (main app example)
398
- rm app/models/post.rb
399
- rm app/controllers/posts_controller.rb
400
- rm app/definitions/post_definition.rb
401
- rm app/policies/post_policy.rb
402
-
403
- # Create migration to drop table
404
- rails g migration DropPosts
119
+ rails g pu:res:scaffold Blogging::Post title:string --dest=blogging
120
+ rails g pu:res:conn Blogging::Post --dest=admin_portal
405
121
  ```
406
122
 
407
- ## Best Practices
123
+ See [Creating packages](./creating-packages) for the package structure.
408
124
 
409
- ### 1. Always Specify `--dest`
410
- Avoids interactive prompts and makes commands reproducible.
125
+ ## Cross-package references
411
126
 
412
- ### 2. Quote Special Characters
413
- Fields with `?` or `{}` must be quoted to prevent shell expansion:
414
127
  ```bash
415
- rails g pu:res:scaffold Post 'content:text?' 'price:decimal{10,2}' --dest=main_app
416
- ```
417
-
418
- ### 3. Run Migrations Before Connecting
419
- ```bash
420
- rails g pu:res:scaffold Post title:string --dest=main_app
421
- rails db:migrate
422
- rails g pu:res:conn Post --dest=admin_portal
128
+ rails g pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=comments
423
129
  ```
424
130
 
425
- ### 4. Review Generated Migrations
426
- Add cascade deletes, composite indexes, and default values as needed.
427
-
428
- ## Troubleshooting
429
-
430
- ### Resource Not Found
431
-
432
- Ensure the resource is connected to the portal with `register_resource`.
433
-
434
- ### Fields Not Showing
435
-
436
- Check that the migration has run and the policy includes the field in `permitted_attributes_for_read`.
437
-
438
- ### Policy Denying Access
439
-
440
- Check the policy's permission methods (`index?`, `show?`, `create?`, etc.) return `true`.
441
-
442
- ### Connection Generator Fails
443
-
444
- Ensure migrations have run - the generator reads model columns to build policy attributes.
131
+ The `blogging/post` syntax expands to `Blogging::Post`.
445
132
 
446
133
  ## Related
447
134
 
448
- - [Creating Packages](./creating-packages)
449
- - [Nested Resources](./nested-resources)
450
- - [Custom Actions](./custom-actions)
135
+ - [Reference › App › Generators](/reference/app/generators) — full generator catalog
136
+ - [Reference › Resource](/reference/resource/) — model + definition + query + actions
137
+ - [Reference › App › Portals](/reference/app/portals) — `pu:res:conn` details
138
+ - [Creating packages](./creating-packages) — resources in feature packages
139
+ - [Nested resources](./nested-resources) — parent/child relationships