plutonium 0.26.8 → 0.26.9

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.
@@ -0,0 +1,535 @@
1
+ # Plutonium Framework Development Guide
2
+
3
+ This guide helps AI agents understand and build Plutonium applications effectively. Plutonium is a Rails RAD framework that extends Rails conventions with application-level concepts.
4
+
5
+ ## Quick Start
6
+
7
+ ### New Application
8
+ ```bash
9
+ rails new app_name -a propshaft -j esbuild -c tailwind \
10
+ -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
11
+ ```
12
+
13
+ ### Essential Commands
14
+ ```bash
15
+ # Setup auth
16
+ rails generate pu:rodauth:install
17
+ rails generate pu:rodauth:account user
18
+
19
+ # Create feature + portal
20
+ rails generate pu:pkg:package blog_management
21
+ rails generate pu:pkg:portal admin_portal
22
+
23
+ # Create complete resource
24
+ rails generate pu:res:scaffold Post user:belongs_to title:string content:text --dest=blog_management
25
+
26
+ # Connect to portal
27
+ rails generate pu:res:conn BlogManagement::Post --dest=admin_portal
28
+ ```
29
+
30
+ ### Start Building
31
+ ```bash
32
+ rails db:migrate
33
+ bin/dev # Visit http://localhost:3000
34
+ ```
35
+
36
+ ## Core Concepts
37
+
38
+ ### 1. Architecture
39
+ - **Packages**: Modular organization using Rails engines
40
+ - **Feature Packages**: Contain business logic (models, interactions, policies)
41
+ - **Portal Packages**: Provide web interfaces with authentication
42
+ - **Resources**: Complete CRUD entities with models, definitions, policies, controllers
43
+ - **Entity Scoping**: Built-in multi-tenancy support
44
+
45
+ ### 2. Key Components
46
+ - **Models**: ActiveRecord + `Plutonium::Resource::Record` for enhanced functionality
47
+ - **Definitions**: Declarative UI configuration (how fields render)
48
+ - **Policies**: Authorization control (what users can access)
49
+ - **Interactions**: Business logic encapsulation (what actions do)
50
+ - **Controllers**: Auto-generated CRUD with customization points
51
+
52
+ ## Essential Generators
53
+
54
+ ### Project Setup
55
+ ```bash
56
+ # New app with Plutonium template
57
+ rails new app_name -a propshaft -j esbuild -c tailwind \
58
+ -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
59
+
60
+ # Add to existing app
61
+ rails generate pu:core:install
62
+ ```
63
+
64
+ ### Authentication Setup (Optional)
65
+
66
+ Authentication is optional in Plutonium. You can build apps without auth using `Plutonium::Auth::Public`. When you do need authentication:
67
+
68
+ #### Basic Setup Workflow
69
+ ```bash
70
+ # 1. Install Rodauth infrastructure
71
+ rails generate pu:rodauth:install
72
+
73
+ # 2. Create account types as needed
74
+ rails generate pu:rodauth:account user
75
+
76
+ # 3. Run migrations
77
+ rails db:migrate
78
+
79
+ # 4. Connect auth to portals (see Portal Integration below)
80
+ ```
81
+
82
+ #### Account Type Options
83
+ ```bash
84
+ # Standard user accounts
85
+ rails generate pu:rodauth:account user
86
+
87
+ # Enhanced admin accounts with MFA and security features
88
+ rails generate pu:rodauth:admin admin
89
+
90
+ # Multi-tenant customer accounts with entity scoping
91
+ rails generate pu:rodauth:customer Customer --entity=Organization
92
+
93
+ # Custom feature set (specify exact features needed)
94
+ rails generate pu:rodauth:account api_user \
95
+ --no-defaults --login --logout --jwt --verify-account
96
+ ```
97
+
98
+ #### Portal Integration
99
+ ```ruby
100
+ # For authenticated portals - add to controller concerns:
101
+ include Plutonium::Auth::Rodauth(:user) # Links to user auth
102
+ include Plutonium::Auth::Rodauth(:admin) # Links to admin auth
103
+
104
+ # For public portals - no authentication required:
105
+ include Plutonium::Auth::Public
106
+
107
+ # This provides: current_user, logout_url helpers in controllers/views
108
+ ```
109
+
110
+ #### Available Auth Features
111
+ - **Core**: `login`, `logout`, `create_account`, `verify_account`, `reset_password`, `change_password`
112
+ - **Security**: `remember`, `lockout`, `active_sessions`, `audit_logging`
113
+ - **MFA**: `otp`, `recovery_codes`, `sms_codes`, `webauthn`
114
+ - **Advanced**: `password_grace_period`, `single_session`, `jwt`, `internal_request`
115
+
116
+ ### Package Generators
117
+ ```bash
118
+ # Create feature package for business logic
119
+ rails generate pu:pkg:package blog_management
120
+
121
+ # Create portal package for web interface
122
+ rails generate pu:pkg:portal admin_dashboard
123
+ ```
124
+
125
+ ### Resource Generators (Most Important)
126
+ ```bash
127
+ # Complete resource scaffold (preferred) - use --dest for package
128
+ rails generate pu:res:scaffold Post user:belongs_to title:string content:text 'published_at:datetime?' --dest=blogging
129
+
130
+ # Referencing namespaced models in associations
131
+ rails generate pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=comments
132
+ rails generate pu:res:scaffold Order customer:belongs_to inventory/product:belongs_to quantity:integer --dest=commerce
133
+
134
+ # Model only - use --dest for package
135
+ rails generate pu:res:model Article title:string body:text author:belongs_to --dest=blogging
136
+ rails generate pu:res:model Review user:belongs_to inventory/product:belongs_to rating:integer --dest=reviews
137
+
138
+ # CRITICAL: Use connection generator to expose resources in portals
139
+ # Always use the generator - NEVER manually connect resources
140
+
141
+ # Use full namespaced path (package_name/model_name format)
142
+ rails generate pu:res:conn blog_management/post blog_management/comment --dest=admin_portal
143
+
144
+ # Interactive mode (will prompt for resource and portal selection)
145
+ rails generate pu:res:conn
146
+
147
+ # The generator handles all routing, controller, and policy connections automatically
148
+ ```
149
+
150
+ ### Other Useful Generators
151
+ ```bash
152
+ # Entity for multi-tenancy
153
+ rails generate pu:res:entity Organization --auth-account=Customer
154
+
155
+ # Eject components for customization
156
+ rails generate pu:eject:layout --dest=admin_portal
157
+ rails generate pu:eject:shell --dest=admin_portal
158
+
159
+ # Development tools
160
+ rails generate pu:gem:annotated # Model annotations
161
+ rails generate pu:gem:standard # Ruby Standard linter
162
+ rails generate pu:gem:dotenv # Environment variables
163
+ ```
164
+
165
+ ## File Structure Patterns
166
+
167
+ ### Feature Package Structure
168
+ ```
169
+ packages/blog_management/
170
+ ├── lib/
171
+ │ └── engine.rb # Package engine
172
+ └── app/
173
+ ├── models/blog_management/
174
+ │ ├── post.rb # Business models
175
+ │ └── resource_record.rb # Base class
176
+ ├── policies/blog_management/
177
+ │ ├── post_policy.rb # Authorization rules
178
+ │ └── resource_policy.rb # Base policy
179
+ ├── definitions/blog_management/
180
+ │ ├── post_definition.rb # UI configuration
181
+ │ └── resource_definition.rb # Base definition
182
+ ├── interactions/blog_management/
183
+ │ └── post_interactions/
184
+ │ └── publish.rb # Business logic
185
+ └── controllers/blog_management/
186
+ └── posts_controller.rb # Optional custom controller
187
+ ```
188
+
189
+ ### Portal Package Structure
190
+ ```
191
+ packages/admin_portal/
192
+ ├── lib/
193
+ │ └── engine.rb # Portal engine
194
+ ├── config/
195
+ │ └── routes.rb # Portal routes
196
+ └── app/
197
+ ├── controllers/admin_portal/
198
+ │ ├── concerns/controller.rb # Auth integration
199
+ │ ├── dashboard_controller.rb # Dashboard
200
+ │ ├── plutonium_controller.rb # Base controller
201
+ │ └── resource_controller.rb # Resource base
202
+ ├── policies/admin_portal/
203
+ │ └── resource_policy.rb # Portal-specific policies
204
+ └── definitions/admin_portal/
205
+ └── resource_definition.rb # Portal-specific definitions
206
+ ```
207
+
208
+ ## Development Patterns
209
+
210
+ ### 1. Resource Definition (UI Configuration)
211
+
212
+ **CRITICAL**: Plutonium automatically detects all fields from your model - database columns, associations, and Active Storage attachments. Definitions should only contain customizations, not field declarations.
213
+
214
+ ```ruby
215
+ class PostDefinition < Plutonium::Resource::Definition
216
+ # NO NEED to declare fields - they're auto-detected from the model
217
+ # Only add customizations below when you want to change default behavior
218
+
219
+ # Form inputs (only override when changing auto-detected behavior)
220
+ input :content, as: :rich_text
221
+ input :published_at, as: :date
222
+ input :category, as: :select, choices: %w[Tech Business]
223
+
224
+ # Display formatting (only override when changing auto-detected behavior)
225
+ display :content, as: :markdown
226
+ display :published_at, as: :datetime
227
+
228
+ # Table columns (only override when changing auto-detected behavior)
229
+ column :published_at, as: :datetime
230
+
231
+ # Search functionality
232
+ search do |scope, query|
233
+ scope.where("title ILIKE ? OR content ILIKE ?", "%#{query}%", "%#{query}%")
234
+ end
235
+
236
+ # Filters (currently only Text filter available)
237
+ filter :status, with: Plutonium::Query::Filters::Text, predicate: :eq
238
+
239
+ # Scopes (named scopes defined on the model. they that appear as filter buttons)
240
+ scope :published
241
+ scope :drafts
242
+
243
+ # Custom actions
244
+ action :publish, interaction: PostInteractions::Publish
245
+ action :archive, interaction: PostInteractions::Archive
246
+ end
247
+ ```
248
+
249
+ ### 2. Policy Configuration (Authorization)
250
+ ```ruby
251
+ class PostPolicy < Plutonium::Resource::Policy
252
+ # Basic permissions (required - secure by default)
253
+ def create?
254
+ user.present?
255
+ end
256
+
257
+ def update?
258
+ record.user_id == user.id || user.admin?
259
+ end
260
+
261
+ def destroy?
262
+ user.admin?
263
+ end
264
+
265
+ # Custom action permissions
266
+ def publish?
267
+ update? && record.published_at.nil?
268
+ end
269
+
270
+ # Attribute permissions (what fields are visible/editable)
271
+ def permitted_attributes_for_read
272
+ attrs = [:title, :content, :published_at, :created_at]
273
+ attrs << :admin_notes if user.admin?
274
+ attrs
275
+ end
276
+
277
+ def permitted_attributes_for_create
278
+ [:title, :content, :user_id]
279
+ end
280
+
281
+ def permitted_attributes_for_update
282
+ permitted_attributes_for_create
283
+ end
284
+
285
+ # Data scoping (what records are visible)
286
+ relation_scope do |scope|
287
+ scope = super(scope) # Important: call super for entity scoping
288
+
289
+ if user.admin?
290
+ scope
291
+ else
292
+ scope.where(user: user).or(scope.where(published: true))
293
+ end
294
+ end
295
+ end
296
+ ```
297
+
298
+ ### 3. Interaction Implementation (Business Logic)
299
+ ```ruby
300
+ module PostInteractions
301
+ class Publish < Plutonium::Resource::Interaction
302
+ # Define what this interaction accepts
303
+ attribute :resource, class: "Post"
304
+ attribute :published_at, :datetime, default: -> { Time.current }
305
+
306
+ # UI presentation
307
+ presents label: "Publish Post",
308
+ icon: Phlex::TablerIcons::Send,
309
+ description: "Make this post public"
310
+
311
+ # Validations
312
+ validates :resource, presence: true
313
+
314
+ private
315
+
316
+ # Business logic
317
+ def execute
318
+ if resource.update(published_at: published_at, status: 'published')
319
+ succeed(resource)
320
+ .with_message("Post published successfully")
321
+ .with_redirect_response(resource_url_for(resource))
322
+ else
323
+ failed(resource.errors)
324
+ end
325
+ end
326
+ end
327
+ end
328
+ ```
329
+
330
+ ### 4. Model Setup
331
+ ```ruby
332
+ class Post < BlogManagement::ResourceRecord
333
+ # Associations
334
+ belongs_to :user
335
+ has_many :comments, dependent: :destroy
336
+ has_one_attached :featured_image
337
+
338
+ # Validations
339
+ validates :title, presence: true
340
+ validates :content, presence: true
341
+
342
+ # Enums
343
+ enum status: { draft: 0, published: 1, archived: 2 }
344
+
345
+ # Scopes
346
+ scope :published, -> { where.not(published_at: nil) }
347
+ scope :recent, -> { order(created_at: :desc) }
348
+
349
+ # Monetary fields (if needed)
350
+ has_cents :price_cents
351
+
352
+ # Custom path parameters (class methods, not instance methods)
353
+ # path_parameter :username # Uses username in URLs
354
+ # dynamic_path_parameter :title # Creates SEO URLs like "1-my-title"
355
+
356
+ # Custom labeling (optional)
357
+ def to_label
358
+ title.presence || "Post ##{id}"
359
+ end
360
+ end
361
+
362
+ # Example with cross-package associations
363
+ class Comment < Comments::ResourceRecord
364
+ belongs_to :user
365
+ belongs_to :post, class_name: "Blogging::Post" # Cross-package reference
366
+
367
+ validates :body, presence: true
368
+ end
369
+ ```
370
+
371
+ ## Best Practices
372
+
373
+ ### 1. File Organization
374
+ - Use packages to organize related features
375
+ - Keep business logic in feature packages
376
+ - Use portal packages for different user interfaces
377
+ - Follow namespacing conventions strictly
378
+
379
+ ### 2. Security First
380
+ - Always define explicit permissions in policies
381
+ - Use relation_scope for data access control
382
+ - Leverage entity scoping for multi-tenancy
383
+ - Test authorization thoroughly
384
+
385
+ ### 3. Generator Usage
386
+ - Start with `pu:res:scaffold` for complete resources
387
+ - Use `--dest=package_name` to specify target package
388
+ - **CRITICAL**: Use `pu:res:conn` generator to connect resources to portals - never manually connect
389
+ - Definitions only need overrides - auto-detection handles defaults
390
+
391
+ ### 4. UI Customization
392
+ - Policies control WHAT (authorization)
393
+ - Definitions control HOW (presentation) - **fields are auto-detected, only add customizations**
394
+ - Interactions control business logic
395
+ - Trust auto-detection, customize only when needed
396
+
397
+ ### 5. Common Field Types
398
+ **Input Types**: `:string`, `:text`, `:rich_text`, `:email`, `:url`, `:tel`, `:password`, `:number`, `:boolean`, `:date`, `:datetime`, `:select`, `:file`, `:uppy`, `:association`
399
+
400
+ **Display Types**: `:string`, `:text`, `:markdown`, `:email`, `:url`, `:boolean`, `:date`, `:datetime`, `:association`, `:attachment`
401
+
402
+ **Action Options**: `category: :primary/:secondary/:danger`, `position: 10`, `record_action: true`, `collection_record_action: true`, `resource_action: true`, `bulk_action: true`, `confirmation: "message"`, `icon: Phlex::TablerIcons::IconName`
403
+
404
+ ## Migration Tips
405
+
406
+ ### Database Setup
407
+ - Use standard Rails migration conventions
408
+ - Always inline indexes and constraints in create_table blocks
409
+ - Use nullable fields with `'field:type?'` syntax
410
+ - Reference namespaced models: `package_name/model:belongs_to`
411
+ - Leverage Rails associations (`belongs_to`, `has_many`, etc.)
412
+
413
+ ### Cross-Package Associations
414
+ ```bash
415
+ # When generating models that reference other packages
416
+ rails generate pu:res:scaffold Comment user:belongs_to blogging/post:belongs_to body:text --dest=comments
417
+
418
+ # This creates the correct association:
419
+ # belongs_to :post, class_name: "Blogging::Post"
420
+ ```
421
+
422
+ ### Entity Scoping (Multi-Tenancy) Setup
423
+
424
+ Plutonium provides powerful multi-tenancy through Entity Scoping, which automatically isolates data by tenant.
425
+
426
+ #### 1. Configure Portal Engine
427
+ ```ruby
428
+ # In packages/admin_portal/lib/engine.rb
429
+ scope_to_entity Organization, strategy: :path # URLs: /organizations/:organization_id/posts
430
+
431
+ # Custom strategy (subdomain-based)
432
+ scope_to_entity Organization, strategy: :current_organization # URLs: /posts on acme.app.com
433
+
434
+ # Custom parameter name
435
+ scope_to_entity Client, strategy: :path, param_key: :client_slug # URLs: /clients/:client_slug/posts
436
+ ```
437
+
438
+ #### 2. Implement Custom Strategy Methods
439
+ ```ruby
440
+ # In packages/customer_portal/app/controllers/customer_portal/concerns/controller.rb
441
+ private
442
+
443
+ def current_organization
444
+ @current_organization ||= begin
445
+ organization = Organization.find_by!(subdomain: request.subdomain)
446
+
447
+ # CRITICAL: Verify user has access to this organization
448
+ unless current_user.organizations.include?(organization)
449
+ raise ActionPolicy::Unauthorized, "Access denied to organization"
450
+ end
451
+
452
+ organization
453
+ end
454
+ rescue ActiveRecord::RecordNotFound
455
+ redirect_to root_path, error: "Invalid organization subdomain"
456
+ end
457
+ ```
458
+
459
+ #### 3. Model Association Setup
460
+ ```ruby
461
+ # Direct association (preferred)
462
+ class Post < ApplicationRecord
463
+ belongs_to :organization # Direct link
464
+ end
465
+
466
+ # Indirect association (automatic chain discovery)
467
+ class Comment < ApplicationRecord
468
+ belongs_to :post
469
+ has_one :organization, through: :post # Chain: Comment -> Post -> Organization
470
+ end
471
+
472
+ # Custom scope for complex relationships
473
+ class Invoice < ApplicationRecord
474
+ belongs_to :customer
475
+
476
+ scope :associated_with_organization, ->(organization) do
477
+ joins(customer: :organization_memberships)
478
+ .where(organization_memberships: { organization_id: organization.id })
479
+ end
480
+ end
481
+ ```
482
+
483
+ #### 4. Policy Integration
484
+ ```ruby
485
+ class PostPolicy < Plutonium::Resource::Policy
486
+ authorize :entity_scope, allow_nil: true # Access to current tenant
487
+
488
+ def update?
489
+ # Ensure record belongs to current tenant AND user can edit
490
+ record.organization == entity_scope && record.author == user
491
+ end
492
+
493
+ relation_scope do |relation|
494
+ relation = super(relation) # Apply entity scoping first
495
+
496
+ # Add additional tenant-aware filtering
497
+ user.admin? ? relation : relation.where(published: true)
498
+ end
499
+ end
500
+ ```
501
+
502
+ ## Quick Reference Commands
503
+
504
+ ```bash
505
+ # Essential workflow
506
+ rails generate pu:pkg:package feature_name # Create feature package
507
+ rails generate pu:res:scaffold Resource --dest=feature_name # Create complete resource
508
+ rails generate pu:pkg:portal portal_name # Create portal
509
+ rails generate pu:res:conn Feature::Resource --dest=portal # CRITICAL: Always use generator to connect
510
+
511
+ # Authentication
512
+ rails generate pu:rodauth:install # Install auth system
513
+ rails generate pu:rodauth:account user # Create user account
514
+ rails generate pu:rodauth:admin admin # Create admin account
515
+
516
+ # Database
517
+ rails db:migrate # Run migrations
518
+ rails db:seed # Seed data
519
+
520
+ # Development
521
+ rails server # Start server
522
+ rails console # Rails console
523
+ rails runner "code" # Run code (prefer over console)
524
+ ```
525
+
526
+ ## Troubleshooting
527
+
528
+ ### Common Issues
529
+ - **Missing permissions**: Check policy methods return true
530
+ - **Fields not showing**: Verify policy permits attributes
531
+ - **Actions not visible**: Ensure action policy method exists
532
+ - **Routing errors**: Check portal routes registration
533
+ - **Package not loading**: Verify engine is properly configured
534
+
535
+ This guide provides the foundation for building robust Plutonium applications with proper separation of concerns, security, and maintainability.
@@ -8,6 +8,8 @@ module Plutonium
8
8
 
9
9
  included do
10
10
  add_flash_types :success, :warning, :error
11
+
12
+ protect_from_forgery with: :null_session, if: -> { request.headers['Authorization'].present? }
11
13
 
12
14
  before_action do
13
15
  next unless defined?(ActiveStorage)
@@ -139,7 +139,7 @@ class ApplicationController < ActionController::Base
139
139
  end
140
140
  else
141
141
  outcome.messages.each { |msg, type| flash.now[type] = msg }
142
- render json: { errors: outcome.errors }, status: :unprocessable_entity
142
+ render json: { errors: outcome.errors }, status: :unprocessable_content
143
143
  end
144
144
  end
145
145
  end
@@ -47,7 +47,7 @@ module Plutonium
47
47
 
48
48
  respond_to do |format|
49
49
  if params[:pre_submit]
50
- format.html { render :new, status: :unprocessable_entity }
50
+ format.html { render :new, status: :unprocessable_content }
51
51
  elsif resource_record!.save
52
52
  format.html do
53
53
  redirect_to redirect_url_after_submit,
@@ -59,10 +59,10 @@ module Plutonium
59
59
  location: redirect_url_after_submit
60
60
  end
61
61
  else
62
- format.html { render :new, status: :unprocessable_entity }
62
+ format.html { render :new, status: :unprocessable_content }
63
63
  format.any do
64
64
  @errors = resource_record!.errors
65
- render "errors", status: :unprocessable_entity
65
+ render "errors", status: :unprocessable_content
66
66
  end
67
67
  end
68
68
  end
@@ -87,7 +87,7 @@ module Plutonium
87
87
 
88
88
  respond_to do |format|
89
89
  if params[:pre_submit]
90
- format.html { render :edit, status: :unprocessable_entity }
90
+ format.html { render :edit, status: :unprocessable_content }
91
91
  elsif resource_record!.save
92
92
  format.html do
93
93
  redirect_to redirect_url_after_submit,
@@ -99,10 +99,10 @@ module Plutonium
99
99
  render :show, status: :ok, location: redirect_url_after_submit
100
100
  end
101
101
  else
102
- format.html { render :edit, status: :unprocessable_entity }
102
+ format.html { render :edit, status: :unprocessable_content }
103
103
  format.any do
104
104
  @errors = resource_record!.errors
105
- render "errors", status: :unprocessable_entity
105
+ render "errors", status: :unprocessable_content
106
106
  end
107
107
  end
108
108
  end
@@ -133,7 +133,7 @@ module Plutonium
133
133
  :existing_references,
134
134
  message: "is referenced by other records"
135
135
 
136
- render "errors", status: :unprocessable_entity
136
+ render "errors", status: :unprocessable_content
137
137
  end
138
138
  end
139
139
  end
@@ -41,7 +41,7 @@ module Plutonium
41
41
  if params[:pre_submit]
42
42
  respond_to do |format|
43
43
  format.html do
44
- render :interactive_record_action, status: :unprocessable_entity
44
+ render :interactive_record_action, status: :unprocessable_content
45
45
  end
46
46
  end
47
47
  return
@@ -65,12 +65,12 @@ module Plutonium
65
65
  end
66
66
  else
67
67
  format.html do
68
- render :interactive_record_action, status: :unprocessable_entity
68
+ render :interactive_record_action, status: :unprocessable_content
69
69
  end
70
70
 
71
71
  format.any do
72
72
  @errors = @interaction.errors
73
- render "errors", status: :unprocessable_entity
73
+ render "errors", status: :unprocessable_content
74
74
  end
75
75
 
76
76
  end
@@ -98,7 +98,7 @@ module Plutonium
98
98
  if params[:pre_submit]
99
99
  respond_to do |format|
100
100
  format.html do
101
- render :interactive_resource_action, status: :unprocessable_entity
101
+ render :interactive_resource_action, status: :unprocessable_content
102
102
  end
103
103
  end
104
104
  return
@@ -122,12 +122,12 @@ module Plutonium
122
122
  end
123
123
  else
124
124
  format.html do
125
- render :interactive_resource_action, status: :unprocessable_entity
125
+ render :interactive_resource_action, status: :unprocessable_content
126
126
  end
127
127
 
128
128
  format.any do
129
129
  @errors = @interaction.errors
130
- render "errors", status: :unprocessable_entity
130
+ render "errors", status: :unprocessable_content
131
131
  end
132
132
 
133
133
  end
@@ -171,11 +171,11 @@ module Plutonium
171
171
  # end
172
172
  # else
173
173
  # format.html do
174
- # render :interactive_bulk_action, status: :unprocessable_entity
174
+ # render :interactive_bulk_action, status: :unprocessable_content
175
175
  # end
176
176
  # format.any do
177
177
  # @errors = @interaction.errors
178
- # render "errors", status: :unprocessable_entity
178
+ # render "errors", status: :unprocessable_content
179
179
  # end
180
180
  # end
181
181
  # end
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- VERSION = "0.26.8"
2
+ VERSION = "0.26.9"
3
3
  NEXT_MAJOR_VERSION = VERSION.split(".").tap { |v|
4
4
  v[1] = v[1].to_i + 1
5
5
  v[2] = 0