plutonium 0.33.1 → 0.34.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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/# Plutonium: The pre-alpha demo.md +4 -2
  3. data/.claude/skills/assets/SKILL.md +416 -0
  4. data/.claude/skills/connect-resource/SKILL.md +112 -0
  5. data/.claude/skills/controller/SKILL.md +302 -0
  6. data/.claude/skills/create-resource/SKILL.md +240 -0
  7. data/.claude/skills/definition/SKILL.md +218 -0
  8. data/.claude/skills/definition-actions/SKILL.md +386 -0
  9. data/.claude/skills/definition-fields/SKILL.md +474 -0
  10. data/.claude/skills/definition-query/SKILL.md +334 -0
  11. data/.claude/skills/forms/SKILL.md +439 -0
  12. data/.claude/skills/installation/SKILL.md +300 -0
  13. data/.claude/skills/interaction/SKILL.md +382 -0
  14. data/.claude/skills/model/SKILL.md +267 -0
  15. data/.claude/skills/model-features/SKILL.md +286 -0
  16. data/.claude/skills/nested-resources/SKILL.md +274 -0
  17. data/.claude/skills/package/SKILL.md +191 -0
  18. data/.claude/skills/policy/SKILL.md +352 -0
  19. data/.claude/skills/portal/SKILL.md +400 -0
  20. data/.claude/skills/resource/SKILL.md +281 -0
  21. data/.claude/skills/rodauth/SKILL.md +452 -0
  22. data/.claude/skills/views/SKILL.md +563 -0
  23. data/Appraisals +46 -4
  24. data/CHANGELOG.md +32 -1
  25. data/app/assets/plutonium.css +2 -2
  26. data/config/brakeman.ignore +239 -0
  27. data/config/initializers/action_policy.rb +1 -1
  28. data/docs/.vitepress/config.ts +132 -47
  29. data/docs/concepts/architecture.md +226 -0
  30. data/docs/concepts/auto-detection.md +254 -0
  31. data/docs/concepts/index.md +61 -0
  32. data/docs/concepts/packages-portals.md +304 -0
  33. data/docs/concepts/resources.md +224 -0
  34. data/docs/cookbook/blog.md +412 -0
  35. data/docs/cookbook/index.md +289 -0
  36. data/docs/cookbook/saas.md +481 -0
  37. data/docs/getting-started/index.md +56 -0
  38. data/docs/getting-started/installation.md +146 -0
  39. data/docs/getting-started/tutorial/01-setup.md +118 -0
  40. data/docs/getting-started/tutorial/02-first-resource.md +180 -0
  41. data/docs/getting-started/tutorial/03-authentication.md +246 -0
  42. data/docs/getting-started/tutorial/04-authorization.md +170 -0
  43. data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
  44. data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
  45. data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
  46. data/docs/getting-started/tutorial/index.md +64 -0
  47. data/docs/guides/adding-resources.md +420 -0
  48. data/docs/guides/authentication.md +551 -0
  49. data/docs/guides/authorization.md +468 -0
  50. data/docs/guides/creating-packages.md +380 -0
  51. data/docs/guides/custom-actions.md +523 -0
  52. data/docs/guides/index.md +45 -0
  53. data/docs/guides/multi-tenancy.md +302 -0
  54. data/docs/guides/nested-resources.md +411 -0
  55. data/docs/guides/search-filtering.md +266 -0
  56. data/docs/guides/theming.md +321 -0
  57. data/docs/index.md +67 -26
  58. data/docs/public/CLAUDE.md +64 -21
  59. data/docs/reference/assets/index.md +496 -0
  60. data/docs/reference/controller/index.md +363 -0
  61. data/docs/reference/definition/actions.md +400 -0
  62. data/docs/reference/definition/fields.md +350 -0
  63. data/docs/reference/definition/index.md +252 -0
  64. data/docs/reference/definition/query.md +342 -0
  65. data/docs/reference/generators/index.md +469 -0
  66. data/docs/reference/index.md +49 -0
  67. data/docs/reference/interaction/index.md +445 -0
  68. data/docs/reference/model/features.md +248 -0
  69. data/docs/reference/model/index.md +219 -0
  70. data/docs/reference/policy/index.md +385 -0
  71. data/docs/reference/portal/index.md +382 -0
  72. data/docs/reference/views/forms.md +396 -0
  73. data/docs/reference/views/index.md +479 -0
  74. data/gemfiles/rails_7.gemfile +9 -2
  75. data/gemfiles/rails_7.gemfile.lock +146 -111
  76. data/gemfiles/rails_8.0.gemfile +20 -0
  77. data/gemfiles/rails_8.0.gemfile.lock +417 -0
  78. data/gemfiles/rails_8.1.gemfile +20 -0
  79. data/gemfiles/rails_8.1.gemfile.lock +419 -0
  80. data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
  81. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
  82. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
  83. data/lib/generators/pu/pkg/portal/USAGE +65 -0
  84. data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
  85. data/lib/generators/pu/res/conn/USAGE +71 -0
  86. data/lib/generators/pu/res/model/USAGE +106 -110
  87. data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
  88. data/lib/generators/pu/res/scaffold/USAGE +85 -0
  89. data/lib/generators/pu/rodauth/install_generator.rb +2 -6
  90. data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
  91. data/lib/generators/pu/skills/sync/USAGE +14 -0
  92. data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
  93. data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
  94. data/lib/plutonium/core/controller.rb +2 -2
  95. data/lib/plutonium/interaction/base.rb +1 -0
  96. data/lib/plutonium/package/engine.rb +2 -2
  97. data/lib/plutonium/query/adhoc_block.rb +6 -2
  98. data/lib/plutonium/query/model_scope.rb +1 -1
  99. data/lib/plutonium/railtie.rb +4 -0
  100. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
  101. data/lib/plutonium/resource/query_object.rb +38 -8
  102. data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
  103. data/lib/plutonium/version.rb +1 -1
  104. data/lib/tasks/release.rake +19 -4
  105. data/package.json +1 -1
  106. metadata +76 -39
  107. data/brakeman.ignore +0 -28
  108. data/docs/api-examples.md +0 -49
  109. data/docs/guide/claude-code-guide.md +0 -74
  110. data/docs/guide/deep-dive/authorization.md +0 -189
  111. data/docs/guide/deep-dive/multitenancy.md +0 -256
  112. data/docs/guide/deep-dive/resources.md +0 -390
  113. data/docs/guide/getting-started/01-installation.md +0 -165
  114. data/docs/guide/index.md +0 -28
  115. data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
  116. data/docs/guide/introduction/02-core-concepts.md +0 -440
  117. data/docs/guide/tutorial/01-project-setup.md +0 -75
  118. data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
  119. data/docs/guide/tutorial/03-defining-resources.md +0 -90
  120. data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
  121. data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
  122. data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
  123. data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
  124. data/docs/markdown-examples.md +0 -85
  125. data/docs/modules/action.md +0 -244
  126. data/docs/modules/authentication.md +0 -236
  127. data/docs/modules/configuration.md +0 -599
  128. data/docs/modules/controller.md +0 -443
  129. data/docs/modules/core.md +0 -316
  130. data/docs/modules/definition.md +0 -1308
  131. data/docs/modules/display.md +0 -759
  132. data/docs/modules/form.md +0 -495
  133. data/docs/modules/generator.md +0 -400
  134. data/docs/modules/index.md +0 -167
  135. data/docs/modules/interaction.md +0 -642
  136. data/docs/modules/package.md +0 -151
  137. data/docs/modules/policy.md +0 -176
  138. data/docs/modules/portal.md +0 -710
  139. data/docs/modules/query.md +0 -297
  140. data/docs/modules/resource_record.md +0 -618
  141. data/docs/modules/routing.md +0 -690
  142. data/docs/modules/table.md +0 -301
  143. data/docs/modules/ui.md +0 -631
@@ -0,0 +1,350 @@
1
+ # Definition Fields
2
+
3
+ Complete reference for field configuration in definitions.
4
+
5
+ ## Core Methods
6
+
7
+ | Method | Applies To | Use When |
8
+ |--------|-----------|----------|
9
+ | `field` | Forms + Show + Table | Universal type override |
10
+ | `input` | Forms only | Form-specific options |
11
+ | `display` | Show page only | Display-specific options |
12
+ | `column` | Table only | Table-specific options |
13
+
14
+ ## Basic Usage
15
+
16
+ ```ruby
17
+ class PostDefinition < Plutonium::Resource::Definition
18
+ # field - changes type everywhere
19
+ field :content, as: :rich_text
20
+
21
+ # input - form-specific
22
+ input :title,
23
+ label: "Article Title",
24
+ hint: "Enter a descriptive title",
25
+ placeholder: "e.g. Getting Started"
26
+
27
+ # display - show page specific
28
+ display :content,
29
+ as: :markdown,
30
+ description: "Published content",
31
+ wrapper: {class: "col-span-full"}
32
+
33
+ # column - table specific
34
+ column :title, label: "Article", align: :center
35
+ column :view_count, align: :end
36
+ end
37
+ ```
38
+
39
+ ## Available Field Types
40
+
41
+ ### Input Types (Forms)
42
+
43
+ | Category | Types |
44
+ |----------|-------|
45
+ | **Text** | `:string`, `:text`, `:email`, `:url`, `:tel`, `:password` |
46
+ | **Rich Text** | `:rich_text`, `:markdown` |
47
+ | **Numeric** | `:number`, `:integer`, `:decimal`, `:range` |
48
+ | **Boolean** | `:boolean` |
49
+ | **Date/Time** | `:date`, `:time`, `:datetime` |
50
+ | **Selection** | `:select`, `:slim_select`, `:radio_buttons`, `:check_boxes` |
51
+ | **Files** | `:file`, `:uppy`, `:attachment` |
52
+ | **Associations** | `:association`, `:secure_association`, `:belongs_to`, `:has_many`, `:has_one` |
53
+ | **Special** | `:hidden`, `:color`, `:phone` |
54
+
55
+ ### Display Types (Show/Index)
56
+
57
+ `:string`, `:text`, `:email`, `:url`, `:phone`, `:markdown`, `:number`, `:integer`, `:decimal`, `:boolean`, `:date`, `:time`, `:datetime`, `:association`, `:attachment`
58
+
59
+ ## Field Options
60
+
61
+ ### Common Options
62
+
63
+ ```ruby
64
+ input :title,
65
+ label: "Custom Label", # Custom label text
66
+ hint: "Help text for forms", # Form help text
67
+ placeholder: "Enter value", # Input placeholder
68
+ description: "For displays" # Display description
69
+ ```
70
+
71
+ ### HTML Attributes
72
+
73
+ ```ruby
74
+ input :title,
75
+ class: "custom-class", # CSS class
76
+ data: {controller: "custom"}, # Data attributes
77
+ required: true, # HTML required
78
+ readonly: true, # HTML readonly
79
+ disabled: true # HTML disabled
80
+ ```
81
+
82
+ ### Wrapper Options
83
+
84
+ ```ruby
85
+ display :content, wrapper: {class: "col-span-full"}
86
+ input :notes, wrapper: {class: "bg-gray-50"}
87
+ ```
88
+
89
+ ## Select/Choices
90
+
91
+ ### Static Choices
92
+
93
+ ```ruby
94
+ input :category, as: :select, choices: %w[Tech Business Lifestyle]
95
+ input :status, as: :select, choices: Post.statuses.keys
96
+ ```
97
+
98
+ ### Dynamic Choices (requires block)
99
+
100
+ ```ruby
101
+ # Basic dynamic
102
+ input :author do |f|
103
+ choices = User.active.pluck(:name, :id)
104
+ f.select_tag choices: choices
105
+ end
106
+
107
+ # With context access
108
+ input :team_members do |f|
109
+ choices = current_user.organization.users.pluck(:name, :id)
110
+ f.select_tag choices: choices
111
+ end
112
+
113
+ # Based on object state
114
+ input :related_posts do |f|
115
+ choices = if object.persisted?
116
+ Post.where.not(id: object.id).published.pluck(:title, :id)
117
+ else
118
+ []
119
+ end
120
+ f.select_tag choices: choices
121
+ end
122
+ ```
123
+
124
+ ## Conditional Rendering
125
+
126
+ ```ruby
127
+ class PostDefinition < Plutonium::Resource::Definition
128
+ # Show based on object state
129
+ display :published_at, condition: -> { object.published? }
130
+ display :rejection_reason, condition: -> { object.rejected? }
131
+
132
+ # Show based on environment
133
+ field :debug_info, condition: -> { Rails.env.development? }
134
+ end
135
+ ```
136
+
137
+ **Note:** Use `condition` for UI state logic. Use **policies** for authorization.
138
+
139
+ ## Dynamic Forms (pre_submit)
140
+
141
+ Use `pre_submit: true` to create forms that dynamically show/hide fields based on other field values.
142
+
143
+ ### Basic Pattern
144
+
145
+ ```ruby
146
+ class PostDefinition < Plutonium::Resource::Definition
147
+ # Trigger field - causes form to re-render on change
148
+ input :send_notifications, pre_submit: true
149
+
150
+ # Dependent field - only shown when condition is true
151
+ input :notification_channel,
152
+ as: :select,
153
+ choices: %w[Email SMS],
154
+ condition: -> { object.send_notifications? }
155
+ end
156
+ ```
157
+
158
+ ### How It Works
159
+
160
+ 1. User changes a `pre_submit: true` field
161
+ 2. Form submits via Turbo (no page reload)
162
+ 3. Server re-renders the form with updated `object` state
163
+ 4. Fields with `condition` procs are re-evaluated
164
+ 5. Newly visible fields appear, hidden fields disappear
165
+
166
+ ## Custom Rendering
167
+
168
+ ### Block Syntax
169
+
170
+ **For Display (can return any component):**
171
+
172
+ ```ruby
173
+ display :status do |field|
174
+ StatusBadgeComponent.new(value: field.value, class: field.dom.css_class)
175
+ end
176
+
177
+ display :metrics do |field|
178
+ if field.value.present?
179
+ MetricsChartComponent.new(data: field.value)
180
+ else
181
+ EmptyStateComponent.new(message: "No metrics")
182
+ end
183
+ end
184
+ ```
185
+
186
+ **For Input (must use form builder methods):**
187
+
188
+ ```ruby
189
+ input :birth_date do |f|
190
+ case object.age_category
191
+ when 'adult'
192
+ f.date_tag(min: 18.years.ago.to_date)
193
+ when 'minor'
194
+ f.date_tag(max: 18.years.ago.to_date)
195
+ else
196
+ f.date_tag
197
+ end
198
+ end
199
+ ```
200
+
201
+ ### phlexi_tag (Advanced Display)
202
+
203
+ ```ruby
204
+ # With component class
205
+ display :status, as: :phlexi_tag, with: StatusBadgeComponent
206
+
207
+ # With inline proc
208
+ display :priority, as: :phlexi_tag, with: ->(value, attrs) {
209
+ case value
210
+ when 'high'
211
+ span(class: "badge badge-danger") { "High" }
212
+ when 'medium'
213
+ span(class: "badge badge-warning") { "Medium" }
214
+ else
215
+ span(class: "badge badge-info") { "Low" }
216
+ end
217
+ }
218
+ ```
219
+
220
+ ### Custom Component Class
221
+
222
+ ```ruby
223
+ input :color_picker, as: ColorPickerComponent
224
+ display :chart, as: ChartComponent
225
+ ```
226
+
227
+ ## Column Alignment
228
+
229
+ ```ruby
230
+ column :title, align: :start # Left (default)
231
+ column :status, align: :center # Center
232
+ column :amount, align: :end # Right
233
+ ```
234
+
235
+ ## Nested Inputs
236
+
237
+ Render inline forms for associated records. Requires `accepts_nested_attributes_for` on the model.
238
+
239
+ ### Model Setup
240
+
241
+ ```ruby
242
+ class Post < ResourceRecord
243
+ has_many :comments
244
+ has_one :metadata
245
+
246
+ accepts_nested_attributes_for :comments, allow_destroy: true, limit: 10
247
+ accepts_nested_attributes_for :metadata, update_only: true
248
+ end
249
+ ```
250
+
251
+ ### Basic Declaration
252
+
253
+ ```ruby
254
+ class PostDefinition < Plutonium::Resource::Definition
255
+ # Block syntax
256
+ nested_input :comments do |n|
257
+ n.input :body, as: :text
258
+ n.input :author_name
259
+ end
260
+
261
+ # Using another definition
262
+ nested_input :metadata, using: PostMetadataDefinition, fields: %i[seo_title seo_description]
263
+ end
264
+ ```
265
+
266
+ ### Options
267
+
268
+ | Option | Description |
269
+ |--------|-------------|
270
+ | `limit` | Max records (auto-detected from model, default: 10) |
271
+ | `allow_destroy` | Show delete checkbox (auto-detected from model) |
272
+ | `update_only` | Hide "Add" button, only edit existing |
273
+ | `description` | Help text above the section |
274
+ | `condition` | Proc to show/hide section |
275
+ | `using` | Reference another Definition class |
276
+ | `fields` | Which fields to render from the definition |
277
+
278
+ ```ruby
279
+ nested_input :amenities,
280
+ allow_destroy: true,
281
+ limit: 20,
282
+ description: "Add property amenities" do |n|
283
+ n.input :name
284
+ n.input :icon, as: :select, choices: ICONS
285
+ end
286
+ ```
287
+
288
+ ## File Uploads
289
+
290
+ ```ruby
291
+ input :avatar, as: :file
292
+ input :avatar, as: :uppy
293
+
294
+ input :documents, as: :file, multiple: true
295
+ input :documents, as: :uppy,
296
+ allowed_file_types: ['.pdf', '.doc'],
297
+ max_file_size: 5.megabytes
298
+ ```
299
+
300
+ ## Common Patterns
301
+
302
+ ### Rich Text Content
303
+
304
+ ```ruby
305
+ field :content, as: :rich_text # Form: rich editor
306
+ display :content, as: :markdown # Show: rendered markdown
307
+ ```
308
+
309
+ ### Money Fields
310
+
311
+ ```ruby
312
+ input :price, as: :decimal, class: "font-mono"
313
+ display :price, class: "font-bold text-green-600"
314
+ ```
315
+
316
+ ### Status Badges
317
+
318
+ ```ruby
319
+ display :status do |field|
320
+ color = case field.value
321
+ when 'active' then 'green'
322
+ when 'pending' then 'yellow'
323
+ else 'gray'
324
+ end
325
+ span(class: "badge badge-#{color}") { field.value.humanize }
326
+ end
327
+ ```
328
+
329
+ ### Hidden Fields
330
+
331
+ ```ruby
332
+ field :author_id, as: :hidden
333
+ input :tenant_id, as: :hidden
334
+ ```
335
+
336
+ ## Context in Blocks
337
+
338
+ Inside `condition` procs and `input` blocks:
339
+ - `object` - The record being edited/displayed
340
+ - `current_user` - The authenticated user
341
+ - `current_parent` - Parent record for nested resources
342
+ - `request`, `params` - Request information
343
+ - All helper methods
344
+
345
+ ## Related
346
+
347
+ - [Definition Reference](./index)
348
+ - [Actions Reference](./actions)
349
+ - [Query Reference](./query)
350
+ - [Forms Reference](/reference/views/forms)
@@ -0,0 +1,252 @@
1
+ # Definition Reference
2
+
3
+ Complete reference for resource definitions.
4
+
5
+ ## Overview
6
+
7
+ Definitions control how resources render - which fields appear in forms, how tables display data, what actions are available.
8
+
9
+ ```ruby
10
+ class PostDefinition < Plutonium::Resource::Definition
11
+ # Field configuration
12
+ field :title
13
+ field :body, as: :rich_text
14
+
15
+ # Form-specific
16
+ input :title, placeholder: "Enter title"
17
+
18
+ # Display-specific
19
+ display :body, as: :markdown
20
+
21
+ # Table columns
22
+ column :title
23
+
24
+ # Custom actions
25
+ action :publish, interaction: PublishPost
26
+
27
+ # Search
28
+ search do |scope, query|
29
+ scope.where("title ILIKE ?", "%#{query}%")
30
+ end
31
+
32
+ # Sorting
33
+ sort :title
34
+ sort :created_at
35
+ default_sort :created_at, :desc
36
+ end
37
+ ```
38
+
39
+ ## Definition Files
40
+
41
+ ### Location
42
+
43
+ ```
44
+ app/definitions/post_definition.rb
45
+ packages/blogging/app/definitions/blogging/post_definition.rb
46
+ ```
47
+
48
+ ### Naming Convention
49
+
50
+ | Model | Definition |
51
+ |-------|------------|
52
+ | `Post` | `PostDefinition` |
53
+ | `Blogging::Post` | `Blogging::PostDefinition` |
54
+
55
+ ### Portal-Specific
56
+
57
+ Override for specific portals:
58
+
59
+ ```ruby
60
+ # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
61
+ module AdminPortal
62
+ class PostDefinition < ::PostDefinition
63
+ # Admin-specific customizations
64
+ field :internal_notes
65
+ end
66
+ end
67
+ ```
68
+
69
+ ## Auto-Detection
70
+
71
+ By default, Plutonium auto-detects fields from the model:
72
+
73
+ ```ruby
74
+ class PostDefinition < Plutonium::Resource::Definition
75
+ # Empty definition = all fields auto-detected
76
+ end
77
+ ```
78
+
79
+ Override selectively:
80
+
81
+ ```ruby
82
+ class PostDefinition < Plutonium::Resource::Definition
83
+ # Override just body field
84
+ field :body, as: :rich_text
85
+
86
+ # Other fields still auto-detected
87
+ end
88
+ ```
89
+
90
+ ## Core Methods
91
+
92
+ ### Field Declaration
93
+
94
+ | Method | Purpose |
95
+ |--------|---------|
96
+ | `field` | Universal type/options for forms, displays, tables |
97
+ | `input` | Form-specific configuration |
98
+ | `display` | Show page configuration |
99
+ | `column` | Table configuration |
100
+
101
+ ### Query Configuration
102
+
103
+ | Method | Purpose |
104
+ |--------|---------|
105
+ | `search` | Full-text search block |
106
+ | `filter` | Sidebar filter inputs |
107
+ | `scope` | Quick filter buttons |
108
+ | `sort` / `sorts` | Sortable columns |
109
+ | `default_sort` | Default sort order |
110
+
111
+ ### Actions
112
+
113
+ | Method | Purpose |
114
+ |--------|---------|
115
+ | `action` | Define custom actions |
116
+ | `nested_input` | Nested forms for associations |
117
+
118
+ ## Page Configuration
119
+
120
+ Configure page titles and descriptions:
121
+
122
+ ```ruby
123
+ class PostDefinition < Plutonium::Resource::Definition
124
+ index_page_title "All Posts"
125
+ index_page_description "Manage your blog posts"
126
+
127
+ new_page_title "Create Post"
128
+ new_page_description "Add a new blog post"
129
+
130
+ show_page_title { |record| record.title }
131
+ show_page_description "View post details"
132
+
133
+ edit_page_title { |record| "Edit: #{record.title}" }
134
+ edit_page_description "Update post content"
135
+ end
136
+ ```
137
+
138
+ ## Breadcrumbs
139
+
140
+ Control breadcrumb display:
141
+
142
+ ```ruby
143
+ class PostDefinition < Plutonium::Resource::Definition
144
+ # Disable breadcrumbs globally
145
+ breadcrumbs false
146
+
147
+ # Or per-page
148
+ index_page_breadcrumbs true
149
+ new_page_breadcrumbs true
150
+ show_page_breadcrumbs true
151
+ edit_page_breadcrumbs true
152
+ interactive_action_page_breadcrumbs true
153
+ end
154
+ ```
155
+
156
+ ## Custom Page Classes
157
+
158
+ Override default page components:
159
+
160
+ ```ruby
161
+ class PostDefinition < Plutonium::Resource::Definition
162
+ # Custom page classes
163
+ class IndexPage < Plutonium::UI::Page::Index
164
+ def render_header
165
+ # Custom header
166
+ end
167
+ end
168
+
169
+ class Form < Plutonium::UI::Form::Resource
170
+ # Custom form behavior
171
+ end
172
+
173
+ class Table < Plutonium::UI::Table::Resource
174
+ # Custom table behavior
175
+ end
176
+
177
+ class Display < Plutonium::UI::Display::Resource
178
+ # Custom display behavior
179
+ end
180
+ end
181
+ ```
182
+
183
+ ## Inheritance
184
+
185
+ Definitions inherit from each other:
186
+
187
+ ```ruby
188
+ # Base definition
189
+ class PostDefinition < Plutonium::Resource::Definition
190
+ field :title
191
+ field :body
192
+ end
193
+
194
+ # Extended definition
195
+ class AdminPortal::PostDefinition < ::PostDefinition
196
+ field :internal_notes
197
+ field :moderation_status
198
+ end
199
+ ```
200
+
201
+ ## Customization Hooks
202
+
203
+ Override customization methods for dynamic configuration:
204
+
205
+ ```ruby
206
+ class PostDefinition < Plutonium::Resource::Definition
207
+ def customize_fields
208
+ field :dynamic_field if some_condition?
209
+ end
210
+
211
+ def customize_inputs
212
+ input :special_input, as: :text
213
+ end
214
+
215
+ def customize_displays
216
+ display :computed_value
217
+ end
218
+
219
+ def customize_columns
220
+ column :extra_column
221
+ end
222
+
223
+ def customize_filters
224
+ filter :status, with: Plutonium::Query::Filters::Text, predicate: :eq
225
+ end
226
+
227
+ def customize_scopes
228
+ scope :active
229
+ end
230
+
231
+ def customize_sorts
232
+ sort :custom_field
233
+ end
234
+
235
+ def customize_actions
236
+ action :dynamic_action, interaction: SomeInteraction
237
+ end
238
+ end
239
+ ```
240
+
241
+ ## Sections
242
+
243
+ - [Fields](./fields) - Form and display field configuration
244
+ - [Actions](./actions) - Custom actions and buttons
245
+ - [Query](./query) - Search, filters, scopes, and sorting
246
+
247
+ ## Related
248
+
249
+ - [Fields](./fields) - Field configuration
250
+ - [Actions](./actions) - Custom actions
251
+ - [Query](./query) - Search, filters, scopes
252
+ - [Views Reference](/reference/views/)