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.
- checksums.yaml +4 -4
- data/# Plutonium: The pre-alpha demo.md +4 -2
- data/.claude/skills/assets/SKILL.md +416 -0
- data/.claude/skills/connect-resource/SKILL.md +112 -0
- data/.claude/skills/controller/SKILL.md +302 -0
- data/.claude/skills/create-resource/SKILL.md +240 -0
- data/.claude/skills/definition/SKILL.md +218 -0
- data/.claude/skills/definition-actions/SKILL.md +386 -0
- data/.claude/skills/definition-fields/SKILL.md +474 -0
- data/.claude/skills/definition-query/SKILL.md +334 -0
- data/.claude/skills/forms/SKILL.md +439 -0
- data/.claude/skills/installation/SKILL.md +300 -0
- data/.claude/skills/interaction/SKILL.md +382 -0
- data/.claude/skills/model/SKILL.md +267 -0
- data/.claude/skills/model-features/SKILL.md +286 -0
- data/.claude/skills/nested-resources/SKILL.md +274 -0
- data/.claude/skills/package/SKILL.md +191 -0
- data/.claude/skills/policy/SKILL.md +352 -0
- data/.claude/skills/portal/SKILL.md +400 -0
- data/.claude/skills/resource/SKILL.md +281 -0
- data/.claude/skills/rodauth/SKILL.md +452 -0
- data/.claude/skills/views/SKILL.md +563 -0
- data/Appraisals +46 -4
- data/CHANGELOG.md +32 -1
- data/app/assets/plutonium.css +2 -2
- data/config/brakeman.ignore +239 -0
- data/config/initializers/action_policy.rb +1 -1
- data/docs/.vitepress/config.ts +132 -47
- data/docs/concepts/architecture.md +226 -0
- data/docs/concepts/auto-detection.md +254 -0
- data/docs/concepts/index.md +61 -0
- data/docs/concepts/packages-portals.md +304 -0
- data/docs/concepts/resources.md +224 -0
- data/docs/cookbook/blog.md +412 -0
- data/docs/cookbook/index.md +289 -0
- data/docs/cookbook/saas.md +481 -0
- data/docs/getting-started/index.md +56 -0
- data/docs/getting-started/installation.md +146 -0
- data/docs/getting-started/tutorial/01-setup.md +118 -0
- data/docs/getting-started/tutorial/02-first-resource.md +180 -0
- data/docs/getting-started/tutorial/03-authentication.md +246 -0
- data/docs/getting-started/tutorial/04-authorization.md +170 -0
- data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
- data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
- data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
- data/docs/getting-started/tutorial/index.md +64 -0
- data/docs/guides/adding-resources.md +420 -0
- data/docs/guides/authentication.md +551 -0
- data/docs/guides/authorization.md +468 -0
- data/docs/guides/creating-packages.md +380 -0
- data/docs/guides/custom-actions.md +523 -0
- data/docs/guides/index.md +45 -0
- data/docs/guides/multi-tenancy.md +302 -0
- data/docs/guides/nested-resources.md +411 -0
- data/docs/guides/search-filtering.md +266 -0
- data/docs/guides/theming.md +321 -0
- data/docs/index.md +67 -26
- data/docs/public/CLAUDE.md +64 -21
- data/docs/reference/assets/index.md +496 -0
- data/docs/reference/controller/index.md +363 -0
- data/docs/reference/definition/actions.md +400 -0
- data/docs/reference/definition/fields.md +350 -0
- data/docs/reference/definition/index.md +252 -0
- data/docs/reference/definition/query.md +342 -0
- data/docs/reference/generators/index.md +469 -0
- data/docs/reference/index.md +49 -0
- data/docs/reference/interaction/index.md +445 -0
- data/docs/reference/model/features.md +248 -0
- data/docs/reference/model/index.md +219 -0
- data/docs/reference/policy/index.md +385 -0
- data/docs/reference/portal/index.md +382 -0
- data/docs/reference/views/forms.md +396 -0
- data/docs/reference/views/index.md +479 -0
- data/gemfiles/rails_7.gemfile +9 -2
- data/gemfiles/rails_7.gemfile.lock +146 -111
- data/gemfiles/rails_8.0.gemfile +20 -0
- data/gemfiles/rails_8.0.gemfile.lock +417 -0
- data/gemfiles/rails_8.1.gemfile +20 -0
- data/gemfiles/rails_8.1.gemfile.lock +419 -0
- data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
- data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
- data/lib/generators/pu/pkg/portal/USAGE +65 -0
- data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
- data/lib/generators/pu/res/conn/USAGE +71 -0
- data/lib/generators/pu/res/model/USAGE +106 -110
- data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
- data/lib/generators/pu/res/scaffold/USAGE +85 -0
- data/lib/generators/pu/rodauth/install_generator.rb +2 -6
- data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
- data/lib/generators/pu/skills/sync/USAGE +14 -0
- data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
- data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
- data/lib/plutonium/core/controller.rb +2 -2
- data/lib/plutonium/interaction/base.rb +1 -0
- data/lib/plutonium/package/engine.rb +2 -2
- data/lib/plutonium/query/adhoc_block.rb +6 -2
- data/lib/plutonium/query/model_scope.rb +1 -1
- data/lib/plutonium/railtie.rb +4 -0
- data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
- data/lib/plutonium/resource/query_object.rb +38 -8
- data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
- data/lib/plutonium/version.rb +1 -1
- data/lib/tasks/release.rake +19 -4
- data/package.json +1 -1
- metadata +76 -39
- data/brakeman.ignore +0 -28
- data/docs/api-examples.md +0 -49
- data/docs/guide/claude-code-guide.md +0 -74
- data/docs/guide/deep-dive/authorization.md +0 -189
- data/docs/guide/deep-dive/multitenancy.md +0 -256
- data/docs/guide/deep-dive/resources.md +0 -390
- data/docs/guide/getting-started/01-installation.md +0 -165
- data/docs/guide/index.md +0 -28
- data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
- data/docs/guide/introduction/02-core-concepts.md +0 -440
- data/docs/guide/tutorial/01-project-setup.md +0 -75
- data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
- data/docs/guide/tutorial/03-defining-resources.md +0 -90
- data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
- data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
- data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
- data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
- data/docs/markdown-examples.md +0 -85
- data/docs/modules/action.md +0 -244
- data/docs/modules/authentication.md +0 -236
- data/docs/modules/configuration.md +0 -599
- data/docs/modules/controller.md +0 -443
- data/docs/modules/core.md +0 -316
- data/docs/modules/definition.md +0 -1308
- data/docs/modules/display.md +0 -759
- data/docs/modules/form.md +0 -495
- data/docs/modules/generator.md +0 -400
- data/docs/modules/index.md +0 -167
- data/docs/modules/interaction.md +0 -642
- data/docs/modules/package.md +0 -151
- data/docs/modules/policy.md +0 -176
- data/docs/modules/portal.md +0 -710
- data/docs/modules/query.md +0 -297
- data/docs/modules/resource_record.md +0 -618
- data/docs/modules/routing.md +0 -690
- data/docs/modules/table.md +0 -301
- 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/)
|