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
@@ -0,0 +1,398 @@
|
|
1
|
+
---
|
2
|
+
title: Controller Module
|
3
|
+
---
|
4
|
+
|
5
|
+
# Controller Module
|
6
|
+
|
7
|
+
The Controller module is your gateway to handling HTTP requests in Plutonium applications. It combines Rails' ActionController with Plutonium-specific enhancements to create a powerful, convention-over-configuration approach that eliminates boilerplate while providing enterprise-grade features like authorization and multi-tenancy.
|
8
|
+
|
9
|
+
::: tip Module Organization
|
10
|
+
Controller functionality is distributed across multiple focused modules:
|
11
|
+
- `lib/plutonium/core/controller.rb` - Foundation and core utilities
|
12
|
+
- `lib/plutonium/resource/controller.rb` - Complete CRUD operations
|
13
|
+
- `lib/plutonium/portal/controller.rb` - Portal-specific features and multi-tenancy
|
14
|
+
:::
|
15
|
+
|
16
|
+
## Core Philosophy
|
17
|
+
|
18
|
+
Plutonium's controller system is built on three fundamental principles:
|
19
|
+
|
20
|
+
- **Convention over Configuration**: Intelligent defaults that work out of the box with minimal setup
|
21
|
+
- **Modular Architecture**: Mix and match functionality based on your needs
|
22
|
+
- **Enterprise Readiness**: Built-in authentication, authorization and multi-tenancy
|
23
|
+
|
24
|
+
## Understanding Resource Registration
|
25
|
+
|
26
|
+
Before diving into controllers, it's crucial to understand how Plutonium connects your resources to the web through registration and routing.
|
27
|
+
|
28
|
+
### Registering Resources
|
29
|
+
|
30
|
+
Resources must be registered with each portal to become accessible through the web interface:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# packages/admin_portal/config/routes.rb
|
34
|
+
AdminPortal::Engine.routes.draw do
|
35
|
+
root to: "dashboard#index"
|
36
|
+
|
37
|
+
# Basic resource registration
|
38
|
+
register_resource User
|
39
|
+
register_resource Post
|
40
|
+
register_resource Comment
|
41
|
+
|
42
|
+
# Advanced registration with options
|
43
|
+
register_resource Profile, singular: true # Creates singular routes
|
44
|
+
register_resource Report do
|
45
|
+
# Add custom routes alongside the standard ones
|
46
|
+
member do
|
47
|
+
get :download
|
48
|
+
post :regenerate
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
### What Registration Gives You
|
55
|
+
|
56
|
+
When you register a resource, Plutonium automatically creates:
|
57
|
+
|
58
|
+
1. **Complete CRUD routes**: All standard RESTful endpoints
|
59
|
+
2. **Nested association routes**: Based on your model's `has_many` relationships
|
60
|
+
3. **Interactive action routes**: For custom business operations
|
61
|
+
4. **Entity-scoped routes**: If your portal uses multi-tenancy
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# This simple registration:
|
65
|
+
register_resource Post
|
66
|
+
|
67
|
+
# Automatically generates:
|
68
|
+
# GET /posts # index - list all posts
|
69
|
+
# GET /posts/new # new - form for creating posts
|
70
|
+
# POST /posts # create - handle post creation
|
71
|
+
# GET /posts/:id # show - display a specific post
|
72
|
+
# GET /posts/:id/edit # edit - form for editing posts
|
73
|
+
# PATCH /posts/:id # update - handle post updates
|
74
|
+
# DELETE /posts/:id # destroy - delete posts
|
75
|
+
|
76
|
+
# Plus interactive action routes:
|
77
|
+
# GET /posts/resource_actions/:interactive_action # Resource-level actions
|
78
|
+
# POST /posts/resource_actions/:interactive_action
|
79
|
+
# GET /posts/:id/record_actions/:interactive_action # Individual record actions
|
80
|
+
# POST /posts/:id/record_actions/:interactive_action
|
81
|
+
|
82
|
+
# Plus nested routes for associations (if Post has_many :comments):
|
83
|
+
# GET /posts/:post_id/nested_comments
|
84
|
+
```
|
85
|
+
|
86
|
+
### Entity Scoping in Routes
|
87
|
+
|
88
|
+
If your portal is scoped to an entity (like Organization), all routes are automatically nested:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
# Engine configuration
|
92
|
+
class AdminPortal::Engine < Rails::Engine
|
93
|
+
include Plutonium::Portal::Engine
|
94
|
+
scope_to_entity Organization, strategy: :path
|
95
|
+
end
|
96
|
+
|
97
|
+
# Your routes become:
|
98
|
+
# GET /:organization_id/posts
|
99
|
+
# GET /:organization_id/posts/:id
|
100
|
+
# All data is automatically scoped to the organization
|
101
|
+
```
|
102
|
+
|
103
|
+
## Controller Components
|
104
|
+
|
105
|
+
### Base Controller: The Foundation
|
106
|
+
|
107
|
+
Every Plutonium controller starts with `Plutonium::Core::Controller`, which provides essential framework integration:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
# app/controllers/application_controller.rb
|
111
|
+
class ApplicationController < ActionController::Base
|
112
|
+
include Plutonium::Core::Controller
|
113
|
+
|
114
|
+
# You now have access to all Plutonium controller features
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
**Key Capabilities:**
|
119
|
+
- **Smart URL Generation**: Automatic resource URL creation with proper routing
|
120
|
+
- **Enhanced Flash Messages**: Extended message types (`:success`, `:warning`, `:error`)
|
121
|
+
- **View Integration**: Automatic view path resolution and layout management
|
122
|
+
- **Resource Management**: Access to registered resources and metadata
|
123
|
+
|
124
|
+
**Essential Methods:**
|
125
|
+
```ruby
|
126
|
+
# URL generation that understands your resource structure
|
127
|
+
resource_url_for(@user) # => "/users/1"
|
128
|
+
resource_url_for(@user, action: :edit) # => "/users/1/edit"
|
129
|
+
resource_url_for(User) # => "/users"
|
130
|
+
|
131
|
+
# Build complex URL arguments for nested resources
|
132
|
+
resource_url_args_for(@user, Post) # => {controller: "/users/posts", user_id: 1}
|
133
|
+
|
134
|
+
# Access application metadata
|
135
|
+
registered_resources # => [User, Post, Comment, ...]
|
136
|
+
|
137
|
+
# Page title management
|
138
|
+
set_page_title("User Profile")
|
139
|
+
make_page_title("Dashboard") # => "Dashboard | MyApp"
|
140
|
+
```
|
141
|
+
|
142
|
+
### Resource Controller: Complete CRUD Operations
|
143
|
+
|
144
|
+
The Resource Controller provides full CRUD functionality with zero configuration:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
class PostsController < ApplicationController
|
148
|
+
include Plutonium::Resource::Controller
|
149
|
+
|
150
|
+
# That's it! All CRUD actions are automatically available:
|
151
|
+
# index, show, new, create, edit, update, destroy
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
**What You Get Automatically:**
|
156
|
+
- **Complete CRUD Operations**: All RESTful actions implemented
|
157
|
+
- **Smart Parameter Handling**: Automatic parameter processing and validation
|
158
|
+
- **Authorization Integration**: Policy checks on every action
|
159
|
+
- **Query Integration**: Automatic filtering, searching, and sorting
|
160
|
+
- **Interaction Support**: Business logic through interaction classes
|
161
|
+
- **Nested Resource Support**: Handles parent-child relationships automatically
|
162
|
+
- **Pagination**: Built-in pagination with sensible defaults
|
163
|
+
|
164
|
+
**Key Methods Available:**
|
165
|
+
```ruby
|
166
|
+
# Resource management
|
167
|
+
resource_class # => Post
|
168
|
+
resource_record! # => @post (raises if not found)
|
169
|
+
resource_record? # => @post or nil
|
170
|
+
current_parent # => parent record for nested routes
|
171
|
+
|
172
|
+
# Parameter handling with automatic authorization
|
173
|
+
resource_params # => processed params with proper scoping
|
174
|
+
submitted_resource_params # => raw submitted parameters
|
175
|
+
|
176
|
+
# View builders for consistent UI
|
177
|
+
build_form # => form builder for the resource
|
178
|
+
build_detail # => detail view builder
|
179
|
+
build_collection # => collection view builder
|
180
|
+
|
181
|
+
# Query objects for data access
|
182
|
+
current_query_object # => handles filtering, searching, sorting
|
183
|
+
```
|
184
|
+
|
185
|
+
### Portal Controller: Multi-Tenancy and Segmentation
|
186
|
+
|
187
|
+
Portal Controllers provide specialized functionality for multi-tenant applications and user segmentation:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
module AdminPortal
|
191
|
+
class PostsController < PlutoniumController
|
192
|
+
include AdminPortal::Concerns::Controller
|
193
|
+
|
194
|
+
# Automatically inherits from ::PostsController
|
195
|
+
# Includes portal-specific concerns and scoping
|
196
|
+
end
|
197
|
+
end
|
198
|
+
```
|
199
|
+
|
200
|
+
## Controller Concerns: Modular Functionality
|
201
|
+
|
202
|
+
Plutonium's controller system uses several modular concerns that provide specific capabilities:
|
203
|
+
|
204
|
+
### Bootable: Initialization and Setup
|
205
|
+
|
206
|
+
Handles the foundational setup that makes everything work smoothly:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
# Automatically included - provides:
|
210
|
+
# ✓ Package detection and engine resolution
|
211
|
+
# ✓ View path configuration for proper template loading
|
212
|
+
# ✓ Flash message type registration
|
213
|
+
|
214
|
+
# Available methods:
|
215
|
+
current_package # => current package module (e.g., AdminPortal)
|
216
|
+
current_engine # => current Rails engine instance
|
217
|
+
```
|
218
|
+
|
219
|
+
### Entity Scoping: Multi-Tenancy Made Simple
|
220
|
+
|
221
|
+
Provides powerful multi-tenancy capabilities with automatic data scoping:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
# Check if the controller is scoped to an entity
|
225
|
+
scoped_to_entity? # => true/false
|
226
|
+
|
227
|
+
# Get the current scoped entity
|
228
|
+
current_scoped_entity # => current organization/tenant
|
229
|
+
|
230
|
+
# Access scoping configuration
|
231
|
+
scoped_entity_strategy # => :path, :subdomain, :custom_method
|
232
|
+
scoped_entity_param_key # => :organization_id
|
233
|
+
scoped_entity_class # => Organization
|
234
|
+
```
|
235
|
+
|
236
|
+
#### Setting Up Entity Scoping
|
237
|
+
|
238
|
+
Configure scoping at the engine level and implement custom strategies as needed:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
# 1. Configure in your engine
|
242
|
+
class AdminPortal::Engine < Rails::Engine
|
243
|
+
include Plutonium::Portal::Engine
|
244
|
+
|
245
|
+
# Path-based scoping (URLs like /organizations/123/posts)
|
246
|
+
scope_to_entity Organization, strategy: :path
|
247
|
+
|
248
|
+
# Or custom strategy for more control
|
249
|
+
scope_to_entity Organization, strategy: :current_organization
|
250
|
+
end
|
251
|
+
|
252
|
+
# 2. For custom strategies, implement the method in your controller concern
|
253
|
+
module AdminPortal::Concerns::Controller
|
254
|
+
private
|
255
|
+
|
256
|
+
# Method name MUST match the strategy name exactly
|
257
|
+
def current_organization
|
258
|
+
# Custom logic - could be subdomain, session, JWT, etc.
|
259
|
+
@current_organization ||= begin
|
260
|
+
# Primary: subdomain lookup
|
261
|
+
Organization.find_by(subdomain: request.subdomain) ||
|
262
|
+
# Fallback: session-based lookup
|
263
|
+
current_user.organizations.find(session[:org_id])
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
### Authorizable: Comprehensive Security
|
270
|
+
|
271
|
+
Integrates with ActionPolicy to provide robust authorization throughout your application:
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
# Authorization methods that work automatically
|
275
|
+
authorize_current!(resource_record!) # Check permissions for current resource
|
276
|
+
authorize_current!(resource_class) # Check permissions for resource class
|
277
|
+
authorize_current!(record, to: :interactive_action?) # Check specific action permission
|
278
|
+
|
279
|
+
# Policy access and queries
|
280
|
+
current_policy # Get policy for current resource
|
281
|
+
current_policy.allowed_to?(:show?) # Check if action is allowed
|
282
|
+
policy_for(@user) # Get policy for specific resource
|
283
|
+
authorized_resource_scope(User) # Get authorized scope for resource class
|
284
|
+
|
285
|
+
# Permission helpers
|
286
|
+
permitted_attributes # Get allowed attributes for current action
|
287
|
+
permitted_associations # Get allowed associations
|
288
|
+
```
|
289
|
+
|
290
|
+
**Authorization Examples:**
|
291
|
+
```ruby
|
292
|
+
class PostsController < ApplicationController
|
293
|
+
include Plutonium::Resource::Controller
|
294
|
+
|
295
|
+
def index
|
296
|
+
# Authorization is automatically checked against PostPolicy#index?
|
297
|
+
# No additional code needed
|
298
|
+
end
|
299
|
+
|
300
|
+
def custom_publish
|
301
|
+
# Check custom permissions
|
302
|
+
authorize_current!(resource_record!, to: :publish?)
|
303
|
+
|
304
|
+
# Your business logic here
|
305
|
+
PublishPostInteraction.call(post: resource_record!)
|
306
|
+
|
307
|
+
redirect_to resource_url_for(resource_record!), success: "Post published!"
|
308
|
+
end
|
309
|
+
|
310
|
+
def conditional_action
|
311
|
+
# Check permissions before taking action
|
312
|
+
if current_policy.allowed_to?(:edit?)
|
313
|
+
redirect_to resource_url_for(resource_record!, action: :edit)
|
314
|
+
else
|
315
|
+
redirect_to resource_url_for(resource_record!),
|
316
|
+
warning: "You don't have permission to edit this post"
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
private
|
321
|
+
|
322
|
+
def resource_params
|
323
|
+
# Only permit attributes that the policy allows
|
324
|
+
params.require(:post).permit(*permitted_attributes)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
## Advanced Usage Patterns
|
330
|
+
|
331
|
+
|
332
|
+
### Nested Resources: Automatic Relationship Handling
|
333
|
+
|
334
|
+
Plutonium automatically handles nested resources based on your ActiveRecord associations:
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
# Your models define the relationships
|
338
|
+
class User < ResourceRecord
|
339
|
+
has_many :posts
|
340
|
+
has_many :comments
|
341
|
+
end
|
342
|
+
|
343
|
+
class Post < ResourceRecord
|
344
|
+
belongs_to :user
|
345
|
+
has_many :comments
|
346
|
+
end
|
347
|
+
|
348
|
+
# Register resources normally
|
349
|
+
AdminPortal::Engine.routes.draw do
|
350
|
+
register_resource User
|
351
|
+
register_resource Post
|
352
|
+
register_resource Comment
|
353
|
+
end
|
354
|
+
|
355
|
+
# Plutonium automatically creates nested routes:
|
356
|
+
# /users/:user_id/nested_posts
|
357
|
+
# /users/:user_id/nested_comments
|
358
|
+
# /posts/:post_id/nested_comments
|
359
|
+
```
|
360
|
+
|
361
|
+
**Automatic Parent Resolution:**
|
362
|
+
```ruby
|
363
|
+
# In a nested route like /users/123/nested_posts/456
|
364
|
+
current_parent # => User.find(123) - automatically resolved
|
365
|
+
parent_route_param # => :user_id
|
366
|
+
parent_input_param # => :user (the belongs_to association name)
|
367
|
+
|
368
|
+
# Parameters are automatically merged
|
369
|
+
resource_params # => includes user: current_parent
|
370
|
+
```
|
371
|
+
|
372
|
+
**Smart URL Generation:**
|
373
|
+
```ruby
|
374
|
+
# From within a nested controller context
|
375
|
+
resource_url_for(Post) # => "/users/123/nested_posts"
|
376
|
+
resource_url_for(@post) # => "/users/123/nested_posts/456"
|
377
|
+
resource_url_for(@post, action: :edit) # => "/users/123/nested_posts/456/edit"
|
378
|
+
|
379
|
+
# Explicit parent specification
|
380
|
+
resource_url_for(Post, parent: @user) # => "/users/123/nested_posts"
|
381
|
+
```
|
382
|
+
|
383
|
+
### Multi-Format Response Handling
|
384
|
+
|
385
|
+
Plutonium automatically handles different response formats for you.
|
386
|
+
It currently supports HTML, JSON, and Turbo Streams.
|
387
|
+
|
388
|
+
## Related Modules
|
389
|
+
|
390
|
+
The Controller module works seamlessly with other Plutonium components:
|
391
|
+
|
392
|
+
- **[Core](./core.md)**: Foundation and essential utilities
|
393
|
+
- **[Resource Record](./resource_record.md)**: CRUD operations and resource management
|
394
|
+
- **[Portal](./portal.md)**: Multi-tenant portal functionality
|
395
|
+
- **[Authentication](./authentication.md)**: User authentication and session management
|
396
|
+
- **[Policy](./policy.md)**: Authorization and access control
|
397
|
+
- **[Interaction](./interaction.md)**: Business logic encapsulation
|
398
|
+
- **[Routing](./routing.md)**: Resource registration and route generation
|
@@ -0,0 +1,316 @@
|
|
1
|
+
---
|
2
|
+
title: Core Module
|
3
|
+
---
|
4
|
+
|
5
|
+
# Core Module
|
6
|
+
|
7
|
+
The Core module (`Plutonium::Core::Controller`) provides the foundational controller functionality that all Plutonium applications depend on. It's a lean, focused module that handles essential framework integration, URL generation, and controller bootstrapping.
|
8
|
+
|
9
|
+
::: tip
|
10
|
+
The Core module is automatically included when you use `Plutonium::Resource::Controller` or `Plutonium::Portal::Controller`. You typically don't include it directly.
|
11
|
+
:::
|
12
|
+
|
13
|
+
## What the Core Module Provides
|
14
|
+
|
15
|
+
The Core module includes three essential controller concerns:
|
16
|
+
|
17
|
+
- **Bootable**: Package and engine detection with automatic view path configuration
|
18
|
+
- **EntityScoping**: Multi-tenancy support with entity-based scoping
|
19
|
+
- **Authorizable**: ActionPolicy integration for authorization
|
20
|
+
|
21
|
+
## Core Controller Features
|
22
|
+
|
23
|
+
### Smart URL Generation
|
24
|
+
|
25
|
+
The Core module provides intelligent URL generation that works with Plutonium's package system and entity scoping:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# Generate URLs for resources with proper routing context
|
29
|
+
resource_url_for(@user) # => "/users/1"
|
30
|
+
resource_url_for(@user, action: :edit) # => "/users/1/edit"
|
31
|
+
resource_url_for(User) # => "/users"
|
32
|
+
|
33
|
+
# Handle nested resources and packages
|
34
|
+
resource_url_for(@user, Post) # => "/users/1/posts"
|
35
|
+
resource_url_for(@post, parent: @user) # => "/users/1/posts/1"
|
36
|
+
|
37
|
+
# Build URL arguments for complex routing scenarios
|
38
|
+
args = resource_url_args_for(@user, Post)
|
39
|
+
# => {controller: "/users/posts", user_id: 1}
|
40
|
+
```
|
41
|
+
|
42
|
+
### Enhanced Flash Messages
|
43
|
+
|
44
|
+
Extends Rails' default flash types with additional semantic types:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
# Available flash types: :notice, :alert, :success, :warning, :error
|
48
|
+
redirect_to posts_path, success: "Post created successfully!"
|
49
|
+
redirect_to posts_path, warning: "Post saved with warnings"
|
50
|
+
redirect_to posts_path, error: "Failed to save post"
|
51
|
+
```
|
52
|
+
|
53
|
+
### Helper Methods
|
54
|
+
|
55
|
+
The Core module provides several helper methods available in controllers and views:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# Page title management
|
59
|
+
set_page_title("Dashboard")
|
60
|
+
make_page_title("Users") # => "Users | App Name"
|
61
|
+
|
62
|
+
# Package and engine information
|
63
|
+
current_package # => AdminPortal (if in a package)
|
64
|
+
current_engine # => AdminPortal::Engine
|
65
|
+
|
66
|
+
# Resource registry access
|
67
|
+
registered_resources # => Array of registered resource classes
|
68
|
+
|
69
|
+
# Application branding
|
70
|
+
app_name # => Your application name
|
71
|
+
```
|
72
|
+
|
73
|
+
## Package Integration (Bootable)
|
74
|
+
|
75
|
+
The Bootable concern automatically detects which package and engine a controller belongs to:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
# In packages/admin_portal/app/controllers/users_controller.rb
|
79
|
+
class UsersController < PlutoniumController
|
80
|
+
# Automatically detects:
|
81
|
+
# current_package => AdminPortal
|
82
|
+
# current_engine => AdminPortal::Engine
|
83
|
+
|
84
|
+
# View paths automatically configured:
|
85
|
+
# - packages/admin_portal/app/views (prepended)
|
86
|
+
# - app/views (Rails default)
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
### Automatic View Path Configuration
|
91
|
+
|
92
|
+
Each package gets its own view path automatically prepended:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# For AdminPortal::UsersController
|
96
|
+
# View lookup order:
|
97
|
+
# 1. packages/admin_portal/app/views/users/
|
98
|
+
# 2. packages/admin_portal/app/views/
|
99
|
+
# 3. app/views/users/
|
100
|
+
# 4. app/views/
|
101
|
+
```
|
102
|
+
|
103
|
+
## Entity Scoping (Multi-tenancy)
|
104
|
+
|
105
|
+
The EntityScoping concern provides multi-tenancy support when configured:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
# In your engine configuration
|
109
|
+
class AdminPortal::Engine < Rails::Engine
|
110
|
+
include Plutonium::Portal
|
111
|
+
|
112
|
+
# Enable entity scoping
|
113
|
+
scope_to_entity Organization, strategy: :path
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
### Available Scoping Methods
|
118
|
+
|
119
|
+
When entity scoping is enabled:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# Check if scoped to an entity
|
123
|
+
scoped_to_entity? # => true/false
|
124
|
+
|
125
|
+
# Get current scoped entity
|
126
|
+
current_scoped_entity # => #<Organization id: 1>
|
127
|
+
|
128
|
+
# Get scoping configuration
|
129
|
+
scoped_entity_strategy # => :path
|
130
|
+
scoped_entity_param_key # => :organization_id
|
131
|
+
scoped_entity_class # => Organization
|
132
|
+
```
|
133
|
+
|
134
|
+
### Entity Scoping Strategies
|
135
|
+
|
136
|
+
**Path Strategy** (most common):
|
137
|
+
```ruby
|
138
|
+
# URLs include entity parameter: /organizations/1/users
|
139
|
+
scope_to_entity Organization, strategy: :path
|
140
|
+
```
|
141
|
+
|
142
|
+
**Custom Strategy**:
|
143
|
+
```ruby
|
144
|
+
# Define your own scoping method
|
145
|
+
scope_to_entity Organization, strategy: :current_organization
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def current_organization
|
150
|
+
current_user.organization
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
## Authorization Integration (Authorizable)
|
155
|
+
|
156
|
+
The Authorizable concern integrates ActionPolicy for authorization:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
# Authorization is automatically configured with:
|
160
|
+
authorize :user, through: :current_user
|
161
|
+
authorize :entity_scope, through: :entity_scope_for_authorize
|
162
|
+
|
163
|
+
# Helper methods available:
|
164
|
+
policy_for(@user) # Get policy for record
|
165
|
+
authorized_resource_scope(User) # Get authorized scope
|
166
|
+
```
|
167
|
+
|
168
|
+
### Authorization Context
|
169
|
+
|
170
|
+
The Core module provides entity scoping context for authorization:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
# In your policies, you can access:
|
174
|
+
class UserPolicy < ApplicationPolicy
|
175
|
+
def index?
|
176
|
+
# entity_scope is automatically available
|
177
|
+
user.admin? || entity_scope == user.organization
|
178
|
+
end
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
## Framework Integration
|
183
|
+
|
184
|
+
### ActiveStorage Integration
|
185
|
+
|
186
|
+
Automatically configures ActiveStorage URL options:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
# Configured in before_action
|
190
|
+
ActiveStorage::Current.url_options = {
|
191
|
+
protocol: request.protocol,
|
192
|
+
host: request.host,
|
193
|
+
port: request.port
|
194
|
+
}
|
195
|
+
```
|
196
|
+
|
197
|
+
### Layout Configuration
|
198
|
+
|
199
|
+
Sets up dynamic layout selection:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
# Automatically uses 'resource' layout unless in Turbo Frame
|
203
|
+
layout -> { turbo_frame_request? ? false : "resource" }
|
204
|
+
```
|
205
|
+
|
206
|
+
### Helper Integration
|
207
|
+
|
208
|
+
Includes all Plutonium helpers:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
helper Plutonium::Helpers
|
212
|
+
# Includes: ApplicationHelper, AttachmentHelper, ContentHelper,
|
213
|
+
# DisplayHelper, TableHelper, TurboHelper, etc.
|
214
|
+
```
|
215
|
+
|
216
|
+
## Usage Patterns
|
217
|
+
|
218
|
+
### Basic Controller Setup
|
219
|
+
|
220
|
+
The Core module is typically used through other Plutonium modules:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
# For resource controllers
|
224
|
+
class UsersController < PlutoniumController
|
225
|
+
include Plutonium::Resource::Controller
|
226
|
+
# Core module included automatically
|
227
|
+
end
|
228
|
+
|
229
|
+
# For portal controllers
|
230
|
+
class DashboardController < PlutoniumController
|
231
|
+
include Plutonium::Portal::Controller
|
232
|
+
# Core module included automatically
|
233
|
+
end
|
234
|
+
```
|
235
|
+
|
236
|
+
### Direct Usage (Advanced)
|
237
|
+
|
238
|
+
If you need just the core functionality:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
class CustomController < ApplicationController
|
242
|
+
include Plutonium::Core::Controller
|
243
|
+
|
244
|
+
def index
|
245
|
+
set_page_title("Custom Page")
|
246
|
+
# Core functionality available
|
247
|
+
end
|
248
|
+
end
|
249
|
+
```
|
250
|
+
|
251
|
+
## Configuration
|
252
|
+
|
253
|
+
The Core module respects Plutonium's main configuration:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
# config/initializers/plutonium.rb
|
257
|
+
Plutonium.configure do |config|
|
258
|
+
config.load_defaults 1.0
|
259
|
+
|
260
|
+
# These affect Core module behavior:
|
261
|
+
config.development = Rails.env.development?
|
262
|
+
config.cache_discovery = !Rails.env.development?
|
263
|
+
end
|
264
|
+
```
|
265
|
+
|
266
|
+
## Best Practices
|
267
|
+
|
268
|
+
### URL Generation
|
269
|
+
|
270
|
+
Always use `resource_url_for` instead of Rails' `url_for` for Plutonium resources:
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
# ✅ Good - respects packages and entity scoping
|
274
|
+
resource_url_for(@user)
|
275
|
+
|
276
|
+
# ❌ Avoid - doesn't understand Plutonium routing
|
277
|
+
user_url(@user)
|
278
|
+
```
|
279
|
+
|
280
|
+
### Page Titles
|
281
|
+
|
282
|
+
Set page titles in controller actions for consistent branding:
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
def show
|
286
|
+
set_page_title(resource_record!.to_label)
|
287
|
+
# Automatically becomes "User Name | App Name"
|
288
|
+
end
|
289
|
+
```
|
290
|
+
|
291
|
+
### Package Organization
|
292
|
+
|
293
|
+
Let the Bootable concern handle package detection automatically:
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
# ✅ Good - automatic detection
|
297
|
+
class AdminPortal::UsersController < PlutoniumController
|
298
|
+
# Package and engine automatically detected
|
299
|
+
end
|
300
|
+
|
301
|
+
# ❌ Avoid - manual configuration
|
302
|
+
class UsersController < PlutoniumController
|
303
|
+
def current_package
|
304
|
+
AdminPortal # Don't override unless necessary
|
305
|
+
end
|
306
|
+
end
|
307
|
+
```
|
308
|
+
|
309
|
+
## Integration with Other Modules
|
310
|
+
|
311
|
+
- **[Resource Record](./resource_record.md)** - Builds on Core for full CRUD functionality
|
312
|
+
- **[Portal](./portal.md)** - Uses Core for multi-tenant portal applications
|
313
|
+
- **[Routing](./routing.md)** - Works with Core's URL generation methods
|
314
|
+
- **[Authorization](/guide/deep-dive/authorization.md)** - Integrates with Core's authorization system
|
315
|
+
|
316
|
+
The Core module provides a solid, focused foundation that other Plutonium modules build upon, handling the essential plumbing that makes the framework's conventions work seamlessly.
|