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/.vitepress/config.ts
CHANGED
@@ -9,6 +9,7 @@ export default defineConfig(withMermaid({
|
|
9
9
|
title: "Plutonium",
|
10
10
|
description: "The Ultimate Rapid Application Development Toolkit (RADKit) for Rails",
|
11
11
|
head: [["link", { rel: "icon", href: `${base}favicon.ico` }]],
|
12
|
+
ignoreDeadLinks: 'localhostLinks',
|
12
13
|
themeConfig: {
|
13
14
|
// https://vitepress.dev/reference/default-theme-config
|
14
15
|
logo: "/plutonium.png",
|
@@ -17,38 +18,78 @@ export default defineConfig(withMermaid({
|
|
17
18
|
},
|
18
19
|
nav: [
|
19
20
|
{ text: "Home", link: "/" },
|
20
|
-
{ text: "Guide", link: "/guide/
|
21
|
+
{ text: "Guide", link: "/guide/introduction/01-what-is-plutonium" },
|
22
|
+
{ text: "Tutorial", link: "/guide/tutorial/01-project-setup" },
|
23
|
+
{ text: "Modules", link: "/modules/" },
|
21
24
|
{ text: "Demo", link: "https://plutonium-app.onrender.com/" }
|
22
25
|
],
|
23
26
|
sidebar: {
|
24
27
|
'/guide/': [
|
25
|
-
|
28
|
+
{
|
29
|
+
text: "Getting Started",
|
30
|
+
items: [
|
31
|
+
{ text: "Installation", link: "/guide/getting-started/01-installation" },
|
32
|
+
]
|
33
|
+
},
|
26
34
|
{
|
27
35
|
text: "Introduction",
|
28
36
|
items: [
|
29
|
-
{ text: "What is Plutonium?", link: "/guide/what-is-plutonium" },
|
30
|
-
{ text: "
|
37
|
+
{ text: "What is Plutonium?", link: "/guide/introduction/01-what-is-plutonium" },
|
38
|
+
{ text: "Core Concepts", link: "/guide/introduction/02-core-concepts" },
|
31
39
|
]
|
32
40
|
},
|
33
41
|
{
|
34
|
-
text: "
|
42
|
+
text: "Tutorial (Building a Blog)",
|
43
|
+
collapsed: false,
|
35
44
|
items: [
|
36
|
-
{ text: "
|
37
|
-
{ text: "
|
38
|
-
{ text: "
|
39
|
-
{ text: "
|
40
|
-
{ text: "
|
45
|
+
{ text: "1. Project Setup", link: "/guide/tutorial/01-project-setup" },
|
46
|
+
{ text: "2. Creating a Feature Package", link: "/guide/tutorial/02-creating-a-feature-package" },
|
47
|
+
{ text: "3. Defining Resources", link: "/guide/tutorial/03-defining-resources" },
|
48
|
+
{ text: "4. Creating a Portal", link: "/guide/tutorial/04-creating-a-portal" },
|
49
|
+
{ text: "5. Customizing the UI", link: "/guide/tutorial/05-customizing-the-ui" },
|
50
|
+
{ text: "6. Adding Custom Actions", link: "/guide/tutorial/06-adding-custom-actions" },
|
51
|
+
{ text: "7. Implementing Authorization", link: "/guide/tutorial/07-implementing-authorization" },
|
41
52
|
]
|
42
53
|
},
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
{
|
55
|
+
text: "Deep Dive",
|
56
|
+
items: [
|
57
|
+
{ text: "Resources", link: "/guide/deep-dive/resources" },
|
58
|
+
{ text: "Authorization", link: "/guide/deep-dive/authorization" },
|
59
|
+
{ text: "Modules", link: "/modules/" },
|
60
|
+
]
|
61
|
+
},
|
62
|
+
{
|
63
|
+
text: "Developer Tools",
|
64
|
+
items: [
|
65
|
+
{ text: "Cursor Rules", link: "/guide/cursor-rules" },
|
66
|
+
]
|
67
|
+
}
|
68
|
+
],
|
69
|
+
'/modules/': [
|
70
|
+
{
|
71
|
+
text: "Modules",
|
72
|
+
items: [
|
73
|
+
{ text: "Overview", link: "/modules/" },
|
74
|
+
{ text: "Action", link: "/modules/action" },
|
75
|
+
{ text: "Authentication", link: "/modules/authentication" },
|
76
|
+
{ text: "Configuration", link: "/modules/configuration" },
|
77
|
+
{ text: "Core", link: "/modules/core" },
|
78
|
+
{ text: "Definition", link: "/modules/definition" },
|
79
|
+
{ text: "Display", link: "/modules/display" },
|
80
|
+
{ text: "Form", link: "/modules/form" },
|
81
|
+
{ text: "Generator", link: "/modules/generator" },
|
82
|
+
{ text: "Interaction", link: "/modules/interaction" },
|
83
|
+
{ text: "Package", link: "/modules/package" },
|
84
|
+
{ text: "Policy", link: "/modules/policy" },
|
85
|
+
{ text: "Portal", link: "/modules/portal" },
|
86
|
+
{ text: "Query", link: "/modules/query" },
|
87
|
+
{ text: "Resource Record", link: "/modules/resource_record" },
|
88
|
+
{ text: "Routing", link: "/modules/routing" },
|
89
|
+
{ text: "Table", link: "/modules/table" },
|
90
|
+
{ text: "UI", link: "/modules/ui" },
|
91
|
+
]
|
92
|
+
}
|
52
93
|
]
|
53
94
|
},
|
54
95
|
socialLinks: [
|
@@ -0,0 +1,75 @@
|
|
1
|
+
---
|
2
|
+
title: Cursor Rules for Plutonium Development
|
3
|
+
---
|
4
|
+
|
5
|
+
<script setup>
|
6
|
+
import { withBase } from 'vitepress'
|
7
|
+
</script>
|
8
|
+
|
9
|
+
# Cursor Rules for Plutonium Development
|
10
|
+
|
11
|
+
This page provides comprehensive cursor rules for building Plutonium applications effectively. These rules are designed to help AI assistants and developers understand the framework's patterns and best practices.
|
12
|
+
|
13
|
+
## Quick Start
|
14
|
+
|
15
|
+
**Download the Rules File**: <a :href="withBase('/plutonium.mdc')" target="_blank">📄 plutonium.mdc</a>
|
16
|
+
|
17
|
+
**Or download directly from your terminal**:
|
18
|
+
|
19
|
+
::: code-group
|
20
|
+
|
21
|
+
```bash [Unix/Linux/macOS/WSL]
|
22
|
+
mkdir -p .cursor/rules && curl -o .cursor/rules/plutonium.mdc https://radioactive-labs.github.io/plutonium-core/plutonium.mdc
|
23
|
+
```
|
24
|
+
|
25
|
+
```cmd [Windows]
|
26
|
+
mkdir .cursor\rules 2>nul & curl -o .cursor\rules\plutonium.mdc https://radioactive-labs.github.io/plutonium-core/plutonium.mdc
|
27
|
+
```
|
28
|
+
|
29
|
+
:::
|
30
|
+
|
31
|
+
## Using These Rules
|
32
|
+
|
33
|
+
Cursor uses Project Rules stored in `.cursor/rules/` directory:
|
34
|
+
|
35
|
+
1. **Download the rules file**: Right-click the link above and "Save As" to download the `.plutonium.mdc` file
|
36
|
+
2. **Open Cursor Settings** → Rules → Project Rules
|
37
|
+
3. **Click "Add new rule"** and give it a name (e.g., "plutonium")
|
38
|
+
4. **Copy the downloaded content** into the new rule file
|
39
|
+
5. The rule will be saved as `.cursor/rules/plutonium.mdc`
|
40
|
+
|
41
|
+
**Legacy Method**: You can also place the downloaded `.plutonium.mdc` file in your project root, but this method is deprecated.
|
42
|
+
|
43
|
+
## What's Included
|
44
|
+
|
45
|
+
The cursor rules file contains comprehensive guidelines for:
|
46
|
+
|
47
|
+
### 🏗️ **Framework Architecture**
|
48
|
+
- Resource-oriented development patterns
|
49
|
+
- Package architecture (Feature & Portal packages)
|
50
|
+
- Component-based UI with Phlex
|
51
|
+
- Business logic through Interactions
|
52
|
+
|
53
|
+
### 📝 **Resource Development**
|
54
|
+
- **Auto-detection philosophy** - Field types are automatically detected from models
|
55
|
+
- **Definition patterns** - Only override when needed
|
56
|
+
- **Policy-based authorization** - Fine-grained permissions
|
57
|
+
- **Interaction-driven business logic** - Encapsulated operations
|
58
|
+
|
59
|
+
### 🔧 **Development Patterns**
|
60
|
+
- **Generator commands** for scaffolding
|
61
|
+
- **Authentication setup** with Rodauth
|
62
|
+
- **Multi-tenancy** with entity scoping
|
63
|
+
- **Query objects** for filtering and search
|
64
|
+
|
65
|
+
### 🎨 **UI Customization**
|
66
|
+
- **Component architecture** with Phlex
|
67
|
+
- **Custom display blocks** with `phlexi_tag`
|
68
|
+
- **Conditional rendering** with context awareness
|
69
|
+
- **Layout customization** patterns
|
70
|
+
|
71
|
+
### ⚡ **Best Practices**
|
72
|
+
- **Performance optimization** techniques
|
73
|
+
- **Security guidelines** and defaults
|
74
|
+
- **Code organization** principles
|
75
|
+
- **Development workflow** recommendations
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# Deep Dive: Authorization
|
2
|
+
|
3
|
+
Plutonium provides a robust authorization system built on top of [Action Policy](https://actionpolicy.evilmartians.io/). It's designed to be secure by default while offering fine-grained control over every aspect of your application's access control.
|
4
|
+
|
5
|
+
## Core Principles
|
6
|
+
|
7
|
+
Authorization in Plutonium is handled by **Policy** classes. Every resource should have a corresponding policy that inherits from `Plutonium::Resource::Policy`.
|
8
|
+
|
9
|
+
A policy's primary job is to answer the question: "Can the current `user` perform this `action` on this `record`?"
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class PostPolicy < Plutonium::Resource::Policy
|
13
|
+
# Can the user see a list of posts?
|
14
|
+
def index?
|
15
|
+
true # Everyone can see the list
|
16
|
+
end
|
17
|
+
|
18
|
+
# Can the user update this specific post?
|
19
|
+
def update?
|
20
|
+
# `record` is the post instance.
|
21
|
+
# `user` is the current authenticated user.
|
22
|
+
record.author == user || user.admin?
|
23
|
+
end
|
24
|
+
|
25
|
+
# ... other permissions
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
## Secure by Default: The Permission Chain
|
30
|
+
|
31
|
+
Plutonium policies are secure by default. If a permission is not explicitly granted, it's denied. This is achieved through a clear inheritance chain.
|
32
|
+
|
33
|
+
::: code-group
|
34
|
+
```ruby [Core Permissions]
|
35
|
+
# These are the base permissions.
|
36
|
+
# They both default to `false`. You MUST override them.
|
37
|
+
def create?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def read?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
```
|
45
|
+
```ruby [Derived Permissions]
|
46
|
+
# These permissions inherit from the core ones.
|
47
|
+
# You can override them for more granular control.
|
48
|
+
def update?
|
49
|
+
create?
|
50
|
+
end
|
51
|
+
|
52
|
+
def destroy?
|
53
|
+
create?
|
54
|
+
end
|
55
|
+
|
56
|
+
def index?
|
57
|
+
read?
|
58
|
+
end
|
59
|
+
|
60
|
+
def show?
|
61
|
+
read?
|
62
|
+
end
|
63
|
+
```
|
64
|
+
:::
|
65
|
+
|
66
|
+
::: danger Always Define Core Permissions
|
67
|
+
Because `create?` and `read?` default to `false`, you must define them in your policy to grant any access. If `create?` is `false`, then `update?` and `destroy?` will also be `false` unless you explicitly override them.
|
68
|
+
:::
|
69
|
+
|
70
|
+
## Attribute & Association Permissions
|
71
|
+
|
72
|
+
Beyond actions, policies also control access to a resource's data at a granular level.
|
73
|
+
|
74
|
+
### Attribute Permissions
|
75
|
+
|
76
|
+
Attribute permissions control which fields a user can see or submit in a form. They follow a similar inheritance chain.
|
77
|
+
|
78
|
+
::: code-group
|
79
|
+
```ruby [Read Attributes]
|
80
|
+
# Controls which fields are returned for `index` and `show` actions.
|
81
|
+
def permitted_attributes_for_read
|
82
|
+
# By default, auto-detects all columns in development,
|
83
|
+
# but MUST be overridden for production.
|
84
|
+
end
|
85
|
+
```
|
86
|
+
```ruby [Create/Update Attributes]
|
87
|
+
# Controls which fields are allowed in `create` and `update` actions.
|
88
|
+
def permitted_attributes_for_create
|
89
|
+
# By default, auto-detects columns (minus some system ones)
|
90
|
+
# in development, but MUST be overridden for production.
|
91
|
+
end
|
92
|
+
|
93
|
+
def permitted_attributes_for_update
|
94
|
+
# Inherits from `permitted_attributes_for_create` by default.
|
95
|
+
permitted_attributes_for_create
|
96
|
+
end
|
97
|
+
```
|
98
|
+
:::
|
99
|
+
|
100
|
+
::: warning Override in Production
|
101
|
+
The default auto-detection for attributes only works in development to speed up initial scaffolding. You **must** override `permitted_attributes_for_create` and `permitted_attributes_for_read` in your policies for them to work in production.
|
102
|
+
:::
|
103
|
+
|
104
|
+
### Association Permissions
|
105
|
+
|
106
|
+
By default, no associations are permitted. You must explicitly list which related resources can be included.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
class PostPolicy < Plutonium::Resource::Policy
|
110
|
+
def permitted_associations
|
111
|
+
[:comments, :author]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## Scoping: Filtering Collections
|
117
|
+
|
118
|
+
A policy's `relation_scope` is used to filter down a collection of records to only what the current user should see. This is applied automatically on `index` pages.
|
119
|
+
|
120
|
+
::: code-group
|
121
|
+
```ruby [Simple Scope]
|
122
|
+
class PostPolicy < Plutonium::Resource::Policy
|
123
|
+
relation_scope do |relation|
|
124
|
+
if user.admin?
|
125
|
+
relation # Admins see all posts
|
126
|
+
else
|
127
|
+
# Others only see their own posts or published posts
|
128
|
+
relation.where(author: user).or(relation.where(published: true))
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
```ruby [Multi-Tenant Scope]
|
134
|
+
class PostPolicy < Plutonium::Resource::Policy
|
135
|
+
relation_scope do |relation|
|
136
|
+
# `super` applies the portal's entity scoping first
|
137
|
+
# e.g., `relation.associated_with(current_organization)`
|
138
|
+
relation = super(relation)
|
139
|
+
|
140
|
+
# Then, apply additional logic
|
141
|
+
if user.admin?
|
142
|
+
relation
|
143
|
+
else
|
144
|
+
relation.where(published: true)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
```
|
149
|
+
:::
|
150
|
+
|
151
|
+
## Authorization Context
|
152
|
+
|
153
|
+
Policies have access to a `context` object. By default, Plutonium provides two:
|
154
|
+
|
155
|
+
- **`user`**: The current authenticated user. This is **required**.
|
156
|
+
- **`entity_scope`**: The current portal's multi-tenancy record (e.g., the current `Organization`). This is optional.
|
157
|
+
|
158
|
+
You can add your own custom context objects for more complex scenarios.
|
159
|
+
|
160
|
+
::: details Adding Custom Context
|
161
|
+
Imagine you have a separate `Ability` system that you also want to check.
|
162
|
+
|
163
|
+
**1. Define the context in the Policy:**
|
164
|
+
```ruby
|
165
|
+
class PostPolicy < ResourcePolicy
|
166
|
+
authorize :ability, allow_nil: true
|
167
|
+
|
168
|
+
def promote?
|
169
|
+
# You can now use `ability` in your permission checks
|
170
|
+
user.admin? && ability&.can?(:promote, record)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
**2. Provide the context from the Controller:**
|
176
|
+
```ruby
|
177
|
+
class PostsController < ResourceController
|
178
|
+
# This tells the policy how to find the `ability` object.
|
179
|
+
authorize :ability, through: :current_ability
|
180
|
+
|
181
|
+
private
|
182
|
+
|
183
|
+
def current_ability
|
184
|
+
# Your custom logic to find the ability object
|
185
|
+
Ability.new(user)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
```
|
189
|
+
:::
|
@@ -248,3 +248,140 @@ end
|
|
248
248
|
- Remember to scope resources appropriately
|
249
249
|
- Test your interactions and policies
|
250
250
|
:::
|
251
|
+
|
252
|
+
# Deep Dive: Building a Resource
|
253
|
+
|
254
|
+
In Plutonium, a **Resource** is the central concept for managing your application's data. It's more than just a model—it's a complete package that includes the model, controller, policy, views, and all the configuration that ties them together.
|
255
|
+
|
256
|
+
This guide will walk you through building a complete `Post` resource from scratch, demonstrating how Plutonium's different modules work together to create a powerful and consistent user experience.
|
257
|
+
|
258
|
+
## 1. Generating the Resource
|
259
|
+
|
260
|
+
We'll start with the scaffold generator, which creates all the necessary files for our `Post` resource.
|
261
|
+
|
262
|
+
```bash
|
263
|
+
rails generate pu:res:scaffold Post user:belongs_to title:string content:text published_at:datetime
|
264
|
+
```
|
265
|
+
|
266
|
+
This command generates:
|
267
|
+
- A `Post` model with the specified attributes and a `belongs_to :user` association.
|
268
|
+
- A `PostsController`.
|
269
|
+
- A `PostPolicy` with basic permissions.
|
270
|
+
- A `PostDefinition` file, which will be the focus of this guide.
|
271
|
+
|
272
|
+
## 2. Configuring Display & Forms (The Definition File)
|
273
|
+
|
274
|
+
The **Definition** file (`app/definitions/post_definition.rb`) is where you declaratively configure how your resource is displayed and edited. Let's start by defining the fields for our table, detail page, and form.
|
275
|
+
|
276
|
+
::: code-group
|
277
|
+
```ruby [app/definitions/post_definition.rb]
|
278
|
+
class PostDefinition < Plutonium::Resource::Definition
|
279
|
+
# Configure the table (index view)
|
280
|
+
column :user, label: "Author"
|
281
|
+
column :published_at, as: :datetime
|
282
|
+
|
283
|
+
# Configure the detail page (show view)
|
284
|
+
display :user, label: "Author"
|
285
|
+
display :published_at, as: :datetime
|
286
|
+
display :content, as: :rich_text
|
287
|
+
|
288
|
+
# Configure the form (new/edit views)
|
289
|
+
input :user, as: :select, label: "Author" # Explicitly use a select input
|
290
|
+
input :content, as: :rich_text
|
291
|
+
end
|
292
|
+
```
|
293
|
+
```ruby [app/policies/post_policy.rb]
|
294
|
+
# In the policy, we must permit these attributes to be read and written.
|
295
|
+
class PostPolicy < Plutonium::Resource::Policy
|
296
|
+
# ...
|
297
|
+
|
298
|
+
def permitted_attributes_for_read
|
299
|
+
[:title, :user, :published_at, :content]
|
300
|
+
end
|
301
|
+
|
302
|
+
def permitted_attributes_for_create
|
303
|
+
[:title, :user_id, :content]
|
304
|
+
end
|
305
|
+
|
306
|
+
def permitted_attributes_for_update
|
307
|
+
permitted_attributes_for_create
|
308
|
+
end
|
309
|
+
end
|
310
|
+
```
|
311
|
+
:::
|
312
|
+
|
313
|
+
Here, we've used the `display` helper to control the `index` and `show` views, and the `input` helper for the forms. We've also specified `:rich_text` to get a WYSIWYG editor for our content. Notice that we also had to permit these attributes in the policy.
|
314
|
+
|
315
|
+
## 3. Adding a Custom Action
|
316
|
+
|
317
|
+
Standard CRUD is great, but most applications have custom business logic. Let's add a "Publish" action. This involves creating an **Interaction** for the logic and registering it in the definition.
|
318
|
+
|
319
|
+
::: code-group
|
320
|
+
```ruby [app/interactions/post_interactions/publish.rb]
|
321
|
+
module PostInteractions
|
322
|
+
class Publish < Plutonium::Resource::Interaction
|
323
|
+
attribute :resource, class: "Post"
|
324
|
+
|
325
|
+
private
|
326
|
+
|
327
|
+
def execute
|
328
|
+
resource.update(published_at: Time.current)
|
329
|
+
succeed(resource).with_message("Post was successfully published.")
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
```
|
334
|
+
```ruby [app/definitions/post_definition.rb]
|
335
|
+
class PostDefinition < Plutonium::Resource::Definition
|
336
|
+
# ... (display and input helpers)
|
337
|
+
|
338
|
+
action :publish,
|
339
|
+
interaction: "PostInteractions::Publish",
|
340
|
+
category: :primary
|
341
|
+
end
|
342
|
+
```
|
343
|
+
```ruby [app/policies/post_policy.rb]
|
344
|
+
class PostPolicy < Plutonium::Resource::Policy
|
345
|
+
# ... (attribute permissions)
|
346
|
+
|
347
|
+
# An action is only visible if its policy returns true.
|
348
|
+
def publish?
|
349
|
+
# Only show the publish button if the post is not yet published.
|
350
|
+
update? && record.published_at.nil?
|
351
|
+
end
|
352
|
+
end
|
353
|
+
```
|
354
|
+
:::
|
355
|
+
|
356
|
+
We now have a "Publish" button on our `Post` detail page that only appears when appropriate, thanks to the combination of the Interaction, Definition, and Policy.
|
357
|
+
|
358
|
+
## 4. Configuring Search, Filters, and Sorting
|
359
|
+
|
360
|
+
To make our resource table more useful, let's add search, filtering, and sorting capabilities. This is all handled declaratively in the definition file.
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
# app/definitions/post_definition.rb
|
364
|
+
class PostDefinition < Plutonium::Resource::Definition
|
365
|
+
# ... (display, input, and action helpers)
|
366
|
+
|
367
|
+
# Enable full-text search across title and content
|
368
|
+
search do |scope, query|
|
369
|
+
scope.where("title ILIKE :q OR content ILIKE :q", q: "%#{query}%")
|
370
|
+
end
|
371
|
+
|
372
|
+
# Add filters to the sidebar
|
373
|
+
filter :published, with: ->(scope, value) { value ? scope.where.not(published_at: nil) : scope.where(published_at: nil) }, as: :boolean
|
374
|
+
filter :user, as: :select, collection: -> { User.pluck(:name, :id) }
|
375
|
+
|
376
|
+
# Define named scopes that appear as buttons
|
377
|
+
scope :all
|
378
|
+
scope :published, -> { where.not(published_at: nil) }
|
379
|
+
scope :drafts, -> { where(published_at: nil) }
|
380
|
+
|
381
|
+
# Configure which columns are sortable
|
382
|
+
sort :title
|
383
|
+
sort :published_at
|
384
|
+
end
|
385
|
+
```
|
386
|
+
|
387
|
+
With just a few lines of code, we now have a powerful and interactive table view for our posts, complete with a search bar, filter sidebar, scope buttons, and sortable columns. This demonstrates how the **Resource** module integrates seamlessly with the **Query** module.
|
@@ -136,72 +136,6 @@ end
|
|
136
136
|
You can use your existing authentication system by implementing the `current_user` method in `ResourceController`.
|
137
137
|
:::
|
138
138
|
|
139
|
-
<!--
|
140
|
-
## Asset Pipeline Setup
|
141
|
-
|
142
|
-
### JavaScript Setup
|
143
|
-
|
144
|
-
|
145
|
-
Plutonium uses modern JavaScript features. Here's how to set it up:
|
146
|
-
|
147
|
-
1. Install required npm packages:
|
148
|
-
|
149
|
-
::: code-group
|
150
|
-
```bash [importmap]
|
151
|
-
bin/importmap pin @radioactive-labs/plutonium
|
152
|
-
```
|
153
|
-
|
154
|
-
```bash [esbuild]
|
155
|
-
yarn add @radioactive-labs/plutonium
|
156
|
-
```
|
157
|
-
:::
|
158
|
-
|
159
|
-
|
160
|
-
2. Configure JavaScript:
|
161
|
-
|
162
|
-
::: code-group
|
163
|
-
```js [app/javascript/controllers/index.js]
|
164
|
-
import { application } from "controllers/application"
|
165
|
-
import { registerControllers } from "@radioactive-labs/plutonium" // [!code ++]
|
166
|
-
registerControllers(application) // [!code ++]
|
167
|
-
```
|
168
|
-
|
169
|
-
```js [app/javascript/application.js]
|
170
|
-
import "@hotwired/turbo-rails"
|
171
|
-
import "controllers"
|
172
|
-
```
|
173
|
-
:::
|
174
|
-
|
175
|
-
### CSS Setup
|
176
|
-
|
177
|
-
Plutonium uses Tailwind CSS. Configure it in your `tailwind.config.js`:
|
178
|
-
|
179
|
-
```js
|
180
|
-
const defaultTheme = require('tailwindcss/defaultTheme')
|
181
|
-
|
182
|
-
module.exports = {
|
183
|
-
content: [
|
184
|
-
'./app/views/**/*.erb',
|
185
|
-
'./app/helpers/**/*.rb',
|
186
|
-
'./app/javascript/**/*.js',
|
187
|
-
'./app/components/**/*.{erb,rb}',
|
188
|
-
'./node_modules/@radioactive-labs/plutonium/**/*.{js,ts}'
|
189
|
-
],
|
190
|
-
theme: {
|
191
|
-
extend: {
|
192
|
-
fontFamily: {
|
193
|
-
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
194
|
-
},
|
195
|
-
},
|
196
|
-
},
|
197
|
-
plugins: [
|
198
|
-
require('@tailwindcss/forms'),
|
199
|
-
require('flowbite/plugin')
|
200
|
-
],
|
201
|
-
}
|
202
|
-
```
|
203
|
-
-->
|
204
|
-
|
205
139
|
## Optional Enhancements
|
206
140
|
|
207
141
|
### Database Performance
|
@@ -229,42 +163,3 @@ rails generate pu:gem:annotated
|
|
229
163
|
# Set up environment variables
|
230
164
|
rails generate pu:gem:dotenv
|
231
165
|
```
|
232
|
-
|
233
|
-
<!--
|
234
|
-
## Verification
|
235
|
-
|
236
|
-
Verify your installation:
|
237
|
-
|
238
|
-
```bash
|
239
|
-
# Start your Rails server
|
240
|
-
rails server
|
241
|
-
|
242
|
-
# Check your logs for any warnings or errors
|
243
|
-
tail -f log/development.log
|
244
|
-
|
245
|
-
# Generate and test a sample resource
|
246
|
-
rails generate pu:res:scaffold Post title:string content:text
|
247
|
-
```
|
248
|
-
|
249
|
-
Visit `http://localhost:3000/posts` to verify everything is working.
|
250
|
-
-->
|
251
|
-
|
252
|
-
<!--
|
253
|
-
::: tip Next Steps
|
254
|
-
Now that you have Plutonium installed and configured, you're ready to:
|
255
|
-
1. [Create your first resource](/guide/resources/creating-resources)
|
256
|
-
2. [Set up your first package](/guide/packages/creating-packages)
|
257
|
-
3. [Configure authorization](/guide/authorization/basic-setup)
|
258
|
-
:::
|
259
|
-
-->
|
260
|
-
|
261
|
-
<!--
|
262
|
-
### Getting Help
|
263
|
-
|
264
|
-
If you run into issues:
|
265
|
-
|
266
|
-
1. Check the [FAQ](/guide/faq)
|
267
|
-
2. Search [GitHub Issues](https://github.com/radioactive-labs/plutonium-core/issues)
|
268
|
-
3. Join our [Discord Community](https://discord.gg/plutonium)
|
269
|
-
4. Create a new [GitHub Issue](https://github.com/radioactive-labs/plutonium-core/issues/new)
|
270
|
-
-->
|
data/docs/guide/index.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
layout: home
|
3
|
+
title: Plutonium Documentation
|
4
|
+
hero:
|
5
|
+
name: Plutonium Documentation
|
6
|
+
text: A RAD toolkit for Rails
|
7
|
+
tagline: Build better applications, faster.
|
8
|
+
actions:
|
9
|
+
- theme: brand
|
10
|
+
text: Get Started
|
11
|
+
link: /guide/introduction/01-what-is-plutonium
|
12
|
+
- theme: alt
|
13
|
+
text: View on GitHub
|
14
|
+
link: https://github.com/radioactive-labs/plutonium
|
15
|
+
features:
|
16
|
+
- title: Introduction
|
17
|
+
details: Learn about the core concepts and architecture of Plutonium.
|
18
|
+
link: /guide/introduction/01-what-is-plutonium
|
19
|
+
- title: Tutorial
|
20
|
+
details: A step-by-step guide to building your first application.
|
21
|
+
link: /guide/tutorial/01-project-setup
|
22
|
+
- title: Deep Dive Guides
|
23
|
+
details: In-depth explanations of specific Plutonium features.
|
24
|
+
link: /guide/deep-dive/resources
|
25
|
+
- title: Module Documentation
|
26
|
+
details: Detailed documentation for each Plutonium module.
|
27
|
+
link: /modules/
|
28
|
+
---
|