reactive-actions 0.1.0.pre.alpha.1

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.
data/README.md ADDED
@@ -0,0 +1,714 @@
1
+ # ReactiveActions
2
+
3
+ ReactiveActions is a Rails gem that provides a framework for handling reactive actions in your Rails application.
4
+
5
+ ## ๐Ÿšง Status
6
+
7
+ This gem is currently in alpha (0.1.0-alpha.1). The API may change between versions.
8
+
9
+ ## ๐Ÿ“ฆ Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'reactive-actions', '0.1.0-alpha.1'
15
+ ```
16
+
17
+ And then execute:
18
+ ```bash
19
+ $ bundle install
20
+ ```
21
+
22
+ Or install it yourself as:
23
+ ```bash
24
+ gem install reactive-actions --pre
25
+ ```
26
+
27
+ After installing the gem, run the generator to set up the necessary files:
28
+
29
+ ```bash
30
+ $ rails generate reactive_actions:install
31
+ ```
32
+
33
+ ## ๐ŸŽฎ Interactive Installation
34
+
35
+ The install generator provides an interactive setup experience that is fully compatible with Rails 8's native asset pipeline (Propshaft + Importmap):
36
+
37
+ ### Basic Interactive Installation
38
+
39
+ ```bash
40
+ $ rails generate reactive_actions:install
41
+ ```
42
+
43
+ This will guide you through the setup process with prompts like:
44
+
45
+ ```
46
+ Welcome to ReactiveActions installer!
47
+ This will help you set up ReactiveActions in your Rails application.
48
+
49
+ Create ReactiveActions initializer? (recommended) (y/n) y
50
+ โœ“ Created initializer
51
+
52
+ Create app/reactive_actions directory? (y/n) y
53
+ โœ“ Created actions directory
54
+
55
+ Generate example action file? (y/n) y
56
+ What should the example action be called? [example] user_login
57
+ โœ“ Created user_login_action.rb
58
+
59
+ Add ReactiveActions routes to your application? (y/n) y
60
+ Mount path for ReactiveActions: [/reactive_actions] /api/actions
61
+ โœ“ Added route mounting ReactiveActions at /api/actions
62
+
63
+ Add ReactiveActions JavaScript client? (y/n) y
64
+ โœ“ Added JavaScript client to importmap
65
+ โœ“ Added ReactiveActions import to app/javascript/application.js
66
+
67
+ Configure advanced options? (y/n) n
68
+
69
+ ================================================================
70
+ ReactiveActions installation complete!
71
+ ================================================================
72
+ ```
73
+
74
+ ### Installation Options
75
+
76
+ You can also use command line options to skip prompts or customize the installation:
77
+
78
+ ```bash
79
+ # Skip specific components
80
+ $ rails generate reactive_actions:install --skip-routes --skip-javascript
81
+
82
+ # Use custom mount path
83
+ $ rails generate reactive_actions:install --mount-path=/api/reactive
84
+
85
+ # Skip example action generation
86
+ $ rails generate reactive_actions:install --skip-example
87
+
88
+ # Quiet installation with defaults
89
+ $ rails generate reactive_actions:install --quiet
90
+ ```
91
+
92
+ ### Available Options
93
+
94
+ - `--skip-routes` - Skip adding routes to your application
95
+ - `--skip-javascript` - Skip adding JavaScript imports and setup
96
+ - `--skip-example` - Skip generating the example action file
97
+ - `--mount-path=PATH` - Specify custom mount path (default: `/reactive_actions`)
98
+ - `--quiet` - Run installation with minimal output and default settings
99
+
100
+ ### What Gets Installed
101
+
102
+ The generator will:
103
+ - โœ… Add the necessary routes to your `config/routes.rb`
104
+ - โœ… Create the `app/reactive_actions` directory
105
+ - โœ… Generate an example action file (customizable name)
106
+ - โœ… Add JavaScript to your `config/importmap.rb` (Rails 8 native)
107
+ - โœ… Automatically import ReactiveActions in your `application.js`
108
+ - โœ… Create an initializer file with configuration options
109
+ - โœ… Optionally configure advanced settings like custom delegated methods
110
+
111
+ ## โšก Rails 8 Native JavaScript Integration
112
+
113
+ ReactiveActions now uses Rails 8's native JavaScript approach with **Importmap + Propshaft**, providing seamless integration without additional build steps.
114
+
115
+ ### Automatic Setup
116
+
117
+ The installer automatically:
118
+ 1. **Pins the module** in your `config/importmap.rb`:
119
+ ```ruby
120
+ pin "reactive_actions", to: "reactive_actions.js"
121
+ ```
122
+
123
+ 2. **Imports it globally** in your `app/javascript/application.js`:
124
+ ```javascript
125
+ // Import ReactiveActions to make it globally available
126
+ import "reactive_actions"
127
+ ```
128
+
129
+ 3. **Makes it available everywhere** as `window.ReactiveActions`
130
+
131
+ ### Manual Import (Optional)
132
+
133
+ You can also import it explicitly in specific files:
134
+
135
+ ```javascript
136
+ import ReactiveActions from "reactive_actions"
137
+
138
+ // Use it locally
139
+ ReactiveActions.execute('action_name', { param: 'value' })
140
+ ```
141
+
142
+ ### Backward Compatibility
143
+
144
+ The JavaScript client supports both Rails 8 (Importmap) and older setups (Sprockets), automatically detecting and configuring the appropriate approach.
145
+
146
+ ## ๐Ÿš€ Usage
147
+
148
+ ### HTTP API
149
+
150
+ Once installed, you can access the reactive actions by sending requests to your configured endpoint:
151
+
152
+ ```
153
+ GET/POST/PUT/PATCH/DELETE /reactive_actions/execute
154
+ ```
155
+
156
+ Or if you used a custom mount path:
157
+
158
+ ```
159
+ GET/POST/PUT/PATCH/DELETE /your-custom-path/execute
160
+ ```
161
+
162
+ You can pass parameters:
163
+ - `action_name`: The name of the action to execute
164
+ - `action_params`: Parameters for the action
165
+
166
+ Example:
167
+ ```ruby
168
+ # Using Rails
169
+ response = Net::HTTP.post(
170
+ URI.parse("http://localhost:3000/reactive_actions/execute"),
171
+ { action_name: "update_user", action_params: { id: 1, name: "New Name" } }.to_json,
172
+ "Content-Type" => "application/json"
173
+ )
174
+ ```
175
+
176
+ ### Creating Custom Actions
177
+
178
+ You can create custom actions by inheriting from `ReactiveActions::ReactiveAction`:
179
+
180
+ ```ruby
181
+ # app/reactive_actions/update_user_action.rb
182
+ class UpdateUserAction < ReactiveActions::ReactiveAction
183
+ def action
184
+ user = User.find(action_params[:id])
185
+ user.update(action_params[:user_attributes])
186
+
187
+ @result = {
188
+ success: true,
189
+ user: user.as_json
190
+ }
191
+ end
192
+
193
+ def response
194
+ render json: {
195
+ success: true,
196
+ data: @result
197
+ }
198
+ end
199
+ end
200
+ ```
201
+
202
+ ### Action Directory Structure
203
+
204
+ Actions are placed in the `app/reactive_actions` directory structure:
205
+
206
+ ```
207
+ app/
208
+ โ”œโ”€โ”€ reactive_actions/
209
+ โ”‚ โ”œโ”€โ”€ simple_action.rb
210
+ โ”‚ โ”œโ”€โ”€ user_actions/
211
+ โ”‚ โ”‚ โ”œโ”€โ”€ create_user_action.rb
212
+ โ”‚ โ”‚ โ”œโ”€โ”€ update_user_action.rb
213
+ โ”‚ โ”‚ โ””โ”€โ”€ delete_user_action.rb
214
+ โ”‚ โ””โ”€โ”€ product_actions/
215
+ โ”‚ โ”œโ”€โ”€ create_product_action.rb
216
+ โ”‚ โ””โ”€โ”€ update_product_action.rb
217
+ ```
218
+
219
+ Actions in subdirectories are automatically loaded and namespaced under `ReactiveActions`. For example, a file at `app/reactive_actions/user_actions/create_user_action.rb` becomes accessible as `ReactiveActions::CreateUserAction`.
220
+
221
+ ### Action Naming Convention
222
+
223
+ Action files should follow the naming convention:
224
+ - File name: `snake_case_action.rb` (e.g., `update_user_action.rb`)
225
+ - Class name: `CamelCaseAction` (e.g., `UpdateUserAction`)
226
+ - HTTP parameter: `snake_case` without the `_action` suffix (e.g., `update_user`)
227
+
228
+ Examples:
229
+ - `create_user_action.rb` โ†’ `CreateUserAction` โ†’ called with `action_name: "create_user"`
230
+ - `fetch_product_action.rb` โ†’ `FetchProductAction` โ†’ called with `action_name: "fetch_product"`
231
+
232
+ ### Advanced Examples
233
+
234
+ #### Complex Action with Validation and Error Handling
235
+
236
+ ```ruby
237
+ # app/reactive_actions/process_payment_action.rb
238
+ class ProcessPaymentAction < ReactiveActions::ReactiveAction
239
+ def action
240
+ # Validate required parameters
241
+ validate_parameters!
242
+
243
+ # Process the payment
244
+ payment_service = PaymentService.new(
245
+ amount: action_params[:amount],
246
+ currency: action_params[:currency],
247
+ payment_method: action_params[:payment_method]
248
+ )
249
+
250
+ @result = payment_service.process
251
+
252
+ # Log the transaction
253
+ PaymentLog.create(
254
+ amount: action_params[:amount],
255
+ status: @result[:status],
256
+ transaction_id: @result[:transaction_id]
257
+ )
258
+ rescue PaymentError => e
259
+ @error = { type: 'payment_failed', message: e.message }
260
+ rescue ValidationError => e
261
+ @error = { type: 'validation_failed', message: e.message }
262
+ end
263
+
264
+ def response
265
+ if @error
266
+ render json: { success: false, error: @error }, status: :unprocessable_entity
267
+ else
268
+ render json: { success: true, data: @result }
269
+ end
270
+ end
271
+
272
+ private
273
+
274
+ def validate_parameters!
275
+ required_params = %i[amount currency payment_method]
276
+ missing_params = required_params.select { |param| action_params[param].blank? }
277
+
278
+ raise ValidationError, "Missing parameters: #{missing_params.join(', ')}" if missing_params.any?
279
+ raise ValidationError, "Invalid amount" unless action_params[:amount].to_f > 0
280
+ end
281
+ end
282
+ ```
283
+
284
+ #### Action with Background Job Integration
285
+
286
+ ```ruby
287
+ # app/reactive_actions/generate_report_action.rb
288
+ class GenerateReportAction < ReactiveActions::ReactiveAction
289
+ def action
290
+ # Queue the report generation job
291
+ job = ReportGenerationJob.perform_later(
292
+ user_id: action_params[:user_id],
293
+ report_type: action_params[:report_type],
294
+ filters: action_params[:filters] || {}
295
+ )
296
+
297
+ @result = {
298
+ job_id: job.job_id,
299
+ status: 'queued',
300
+ estimated_completion: 5.minutes.from_now
301
+ }
302
+ end
303
+
304
+ def response
305
+ render json: {
306
+ success: true,
307
+ message: 'Report generation started',
308
+ data: @result
309
+ }
310
+ end
311
+ end
312
+ ```
313
+
314
+ ## ๐Ÿ’ป JavaScript Client
315
+
316
+ ReactiveActions includes a modern JavaScript client that's automatically available after installation.
317
+
318
+ ### Global Usage (Recommended)
319
+
320
+ After installation, `ReactiveActions` is globally available:
321
+
322
+ ```javascript
323
+ // Basic usage (POST method by default)
324
+ ReactiveActions.execute('update_user', { id: 1, name: 'New Name' })
325
+ .then(response => {
326
+ if (response.ok) {
327
+ console.log('Success:', response);
328
+ } else {
329
+ console.error('Error:', response);
330
+ }
331
+ });
332
+
333
+ // Using specific HTTP methods
334
+ ReactiveActions.get('fetch_user', { id: 1 });
335
+ ReactiveActions.post('create_user', { name: 'New User' });
336
+ ReactiveActions.put('update_user', { id: 1, name: 'Updated Name' });
337
+ ReactiveActions.patch('partial_update', { id: 1, status: 'active' });
338
+ ReactiveActions.delete('delete_user', { id: 1 });
339
+
340
+ // With custom options
341
+ ReactiveActions.execute('custom_action', { data: 'value' }, {
342
+ method: 'POST',
343
+ contentType: 'application/json'
344
+ });
345
+ ```
346
+
347
+ ### ES Module Import (Advanced)
348
+
349
+ For more control, you can import it explicitly:
350
+
351
+ ```javascript
352
+ import ReactiveActions from "reactive_actions"
353
+
354
+ // Use it in your module
355
+ ReactiveActions.execute('action_name', { param: 'value' })
356
+ ```
357
+
358
+ ### Client Features
359
+
360
+ The client automatically:
361
+ - โœ… **Handles CSRF tokens** - Automatically includes Rails CSRF protection
362
+ - โœ… **Formats requests** - Properly formats GET vs POST/PUT/PATCH/DELETE requests
363
+ - โœ… **Parses responses** - Automatically parses JSON responses
364
+ - โœ… **Returns promises** - Modern async/await compatible
365
+ - โœ… **Error handling** - Provides structured error information
366
+ - โœ… **Multiple HTTP methods** - Support for GET, POST, PUT, PATCH, DELETE
367
+
368
+ ## Security
369
+
370
+ ReactiveActions implements several security measures to protect your application:
371
+
372
+ ### ๐Ÿ”’ **Built-in Security Features**
373
+
374
+ #### Parameter Sanitization
375
+ - **Input validation**: Action names are validated against safe patterns (`/\A[a-zA-Z_][a-zA-Z0-9_]*\z/`)
376
+ - **Parameter key sanitization**: Only alphanumeric characters, underscores, and hyphens allowed
377
+ - **String length limits**: Prevents memory exhaustion attacks (max 10,000 chars)
378
+ - **Dangerous prefix filtering**: Blocks parameters starting with `__`, `eval`, `exec`, `system`, etc.
379
+
380
+ #### CSRF Protection
381
+ - **Automatic CSRF tokens**: JavaScript client automatically includes Rails CSRF tokens
382
+ - **Same-origin requests**: Credentials are sent only to same-origin requests
383
+ - **Controller integration**: Inherits from `ActionController::Base` with CSRF protection
384
+
385
+ #### Code Injection Prevention
386
+ - **Class name validation**: Action names are sanitized before constant lookup
387
+ - **Namespace isolation**: Actions are properly namespaced to prevent conflicts
388
+ - **Parameter filtering**: Recursive parameter sanitization for nested structures
389
+
390
+ ### ๐Ÿ›ก๏ธ **Security Best Practices**
391
+
392
+ ```ruby
393
+ # app/reactive_actions/secure_action.rb
394
+ class SecureAction < ReactiveActions::ReactiveAction
395
+ def action
396
+ # Always validate user permissions
397
+ raise ReactiveActions::UnauthorizedError unless current_user&.admin?
398
+
399
+ # Validate and sanitize inputs
400
+ user_id = action_params[:user_id].to_i
401
+ raise ReactiveActions::InvalidParametersError, "Invalid user ID" if user_id <= 0
402
+
403
+ # Use strong parameters if integrating with models
404
+ permitted_params = action_params.slice(:name, :email).permit!
405
+
406
+ @result = User.find(user_id).update(permitted_params)
407
+ end
408
+ end
409
+ ```
410
+
411
+ ### โš ๏ธ **Security Considerations**
412
+
413
+ - **Always validate user permissions** in your actions
414
+ - **Use Rails strong parameters** when working with model updates
415
+ - **Sanitize file uploads** if handling file parameters
416
+ - **Implement rate limiting** for public-facing actions
417
+ - **Log security events** for audit trails
418
+
419
+ ## Performance
420
+
421
+ ### ๐Ÿš€ **Performance Characteristics**
422
+
423
+ ReactiveActions is designed to be lightweight and efficient:
424
+
425
+ - **Minimal overhead**: Direct controller execution without complex middleware chains
426
+ - **No database dependencies**: Core functionality doesn't require database connections
427
+ - **Efficient autoloading**: Actions are loaded on-demand using Rails' autoloading
428
+ - **Memory efficient**: Parameter sanitization prevents memory exhaustion attacks
429
+
430
+ ### ๐Ÿ“Š **Performance Best Practices**
431
+
432
+ #### Action Design
433
+ ```ruby
434
+ # โœ… Good: Lightweight action with focused responsibility
435
+ class QuickUpdateAction < ReactiveActions::ReactiveAction
436
+ def action
437
+ User.where(id: action_params[:id]).update_all(
438
+ last_seen_at: Time.current
439
+ )
440
+ end
441
+ end
442
+
443
+ # โŒ Avoid: Heavy operations that should be background jobs
444
+ class SlowReportAction < ReactiveActions::ReactiveAction
445
+ def action
446
+ # This should be a background job instead
447
+ @result = generate_complex_report_synchronously
448
+ end
449
+ end
450
+ ```
451
+
452
+ #### Use Background Jobs for Heavy Operations
453
+ ```ruby
454
+ # โœ… Better approach for time-consuming operations
455
+ class InitiateReportAction < ReactiveActions::ReactiveAction
456
+ def action
457
+ ReportGenerationJob.perform_later(action_params)
458
+ @result = { status: 'queued', job_id: SecureRandom.uuid }
459
+ end
460
+ end
461
+ ```
462
+
463
+ #### Optimize Database Queries
464
+ ```ruby
465
+ class OptimizedAction < ReactiveActions::ReactiveAction
466
+ def action
467
+ # Use includes to avoid N+1 queries
468
+ @users = User.includes(:profile, :posts)
469
+ .where(id: action_params[:user_ids])
470
+
471
+ # Use select to limit returned columns
472
+ @summary = User.select(:id, :name, :created_at)
473
+ .where(active: true)
474
+ end
475
+ end
476
+ ```
477
+
478
+ ### ๐Ÿ“ˆ **Monitoring and Optimization**
479
+
480
+ - **Monitor response times**: Actions should typically complete in < 100ms
481
+ - **Use Rails logging**: ReactiveActions logs execution details at debug level
482
+ - **Profile memory usage**: Large parameter sets can impact memory
483
+ - **Consider caching**: Use Rails caching for frequently accessed data
484
+
485
+ ## โš™๏ธ Configuration
486
+
487
+ The gem can be configured using an initializer (automatically created by the install generator):
488
+
489
+ ```ruby
490
+ # config/initializers/reactive_actions.rb
491
+ ReactiveActions.configure do |config|
492
+ # Configure methods to delegate from the controller to action classes
493
+ config.delegated_controller_methods += [:custom_method]
494
+
495
+ # Configure instance variables to delegate from the controller to action classes
496
+ config.delegated_instance_variables += [:custom_variable]
497
+ end
498
+
499
+ # Set the logger for ReactiveActions
500
+ ReactiveActions.logger = Rails.logger
501
+ ```
502
+
503
+ ### Advanced Configuration
504
+
505
+ During installation, you can choose to configure advanced options:
506
+
507
+ - **Custom Controller Methods**: Add additional controller methods to delegate to action classes
508
+ - **Logging Level**: Set a custom logging level for ReactiveActions
509
+ - **Instance Variables**: Configure which instance variables to delegate from controllers to actions
510
+
511
+ ### Default Delegated Methods
512
+
513
+ By default, the following controller methods are available in your actions:
514
+ - `render`
515
+ - `redirect_to`
516
+ - `head`
517
+ - `params`
518
+ - `session`
519
+ - `cookies`
520
+ - `flash`
521
+ - `request`
522
+ - `response`
523
+
524
+ ## โŒ Error Handling
525
+
526
+ ReactiveActions provides structured error handling with specific error types:
527
+
528
+ - `ActionNotFoundError`: When the requested action doesn't exist
529
+ - `MissingParameterError`: When required parameters are missing
530
+ - `InvalidParametersError`: When parameters have invalid types or formats
531
+ - `UnauthorizedError`: When the user lacks permission for the action
532
+ - `ActionExecutionError`: When an error occurs during action execution
533
+
534
+ All errors return JSON responses with consistent structure:
535
+
536
+ ```json
537
+ {
538
+ "success": false,
539
+ "error": {
540
+ "type": "ActionNotFoundError",
541
+ "message": "Action 'non_existent' not found",
542
+ "code": "NOT_FOUND"
543
+ }
544
+ }
545
+ ```
546
+
547
+ ## ๐Ÿ”ง Troubleshooting
548
+
549
+ ### Common Issues and Solutions
550
+
551
+ #### โ“ **Action Not Found Errors**
552
+
553
+ **Problem**: Getting `ActionNotFoundError` for existing actions
554
+
555
+ **Solutions**:
556
+ ```bash
557
+ # 1. Check file naming convention
558
+ # File: app/reactive_actions/my_action.rb
559
+ # Class: MyAction
560
+ # Call with: action_name: "my"
561
+
562
+ # 2. Restart Rails to reload autoloading
563
+ rails restart
564
+
565
+ # 3. Check for syntax errors in action file
566
+ rails console
567
+ > MyAction # Should load without errors
568
+ ```
569
+
570
+ #### โ“ **JavaScript Client Not Working**
571
+
572
+ **Problem**: `ReactiveActions is not defined` in browser
573
+
574
+ **Solutions**:
575
+ ```javascript
576
+ // 1. Check importmap.rb includes the pin
577
+ // config/importmap.rb should have:
578
+ pin "reactive_actions", to: "reactive_actions.js"
579
+
580
+ // 2. Check application.js imports it
581
+ // app/javascript/application.js should have:
582
+ import "reactive_actions"
583
+
584
+ // 3. Clear browser cache and restart Rails
585
+ ```
586
+
587
+ #### โ“ **CSRF Token Errors**
588
+
589
+ **Problem**: Getting `Can't verify CSRF token authenticity`
590
+
591
+ **Solutions**:
592
+ ```erb
593
+ <!-- 1. Ensure CSRF meta tags are in your layout -->
594
+ <%= csrf_meta_tags %>
595
+
596
+ <!-- 2. Check that protect_from_forgery is enabled -->
597
+ <%# In your ApplicationController %>
598
+ protect_from_forgery with: :exception
599
+ ```
600
+
601
+ #### โ“ **Parameter Sanitization Issues**
602
+
603
+ **Problem**: Parameters are being rejected or modified unexpectedly
604
+
605
+ **Solutions**:
606
+ ```ruby
607
+ # 1. Check parameter key format (alphanumeric, underscore, hyphen only)
608
+ # โœ… Good: { user_name: "John", user-id: 123 }
609
+ # โŒ Bad: { "__eval": "code", "system()": "bad" }
610
+
611
+ # 2. Check string length limits (max 10,000 characters)
612
+ # 3. Review logs for specific sanitization messages
613
+ ```
614
+
615
+ #### โ“ **Performance Issues**
616
+
617
+ **Problem**: Actions are slow or timing out
618
+
619
+ **Solutions**:
620
+ ```ruby
621
+ # 1. Move heavy operations to background jobs
622
+ class SlowAction < ReactiveActions::ReactiveAction
623
+ def action
624
+ # Instead of this:
625
+ # heavy_operation
626
+
627
+ # Do this:
628
+ HeavyOperationJob.perform_later(action_params)
629
+ @result = { status: 'queued' }
630
+ end
631
+ end
632
+
633
+ # 2. Optimize database queries
634
+ # 3. Add caching where appropriate
635
+ # 4. Monitor with Rails logs at debug level
636
+ ```
637
+
638
+ ### Debug Mode
639
+
640
+ Enable detailed logging for troubleshooting:
641
+
642
+ ```ruby
643
+ # config/initializers/reactive_actions.rb
644
+ ReactiveActions.logger.level = :debug
645
+
646
+ # This will log:
647
+ # - Action execution details
648
+ # - Parameter sanitization steps
649
+ # - Error stack traces
650
+ # - Performance metrics
651
+ ```
652
+
653
+ ## ๐Ÿš„ Rails 8 Compatibility
654
+
655
+ This gem is designed specifically for Rails 8 and takes advantage of:
656
+
657
+ - โœ… **Propshaft** - Modern asset pipeline without compilation
658
+ - โœ… **Importmap** - Native ES module support without bundling
659
+ - โœ… **Rails 8 conventions** - Follows current Rails best practices
660
+ - โœ… **Modern JavaScript** - ES6+ classes and async/await
661
+ - โœ… **Backward compatibility** - Still works with Sprockets if needed
662
+
663
+ ## ๐Ÿ—บ๏ธ Roadmap & Future Improvements
664
+
665
+ Planned improvements for ReactiveActions:
666
+
667
+ * Security hooks - methods that run before actions for authentication and authorization checks
668
+ * Rate limiting and throttling capabilities
669
+ * Enhanced error handling with more granular error types
670
+ * Action composition - ability to build complex workflows from smaller actions
671
+ * Improved generators for common action patterns
672
+ * Built-in testing utilities and helpers
673
+ * Auto-generated API documentation
674
+ * And much more
675
+
676
+ ## ๐Ÿ› ๏ธ Development
677
+
678
+ After checking out the repo, run the following to install dependencies:
679
+
680
+ ```bash
681
+ $ bundle install
682
+ ```
683
+
684
+ Then, run the tests:
685
+
686
+ ```bash
687
+ $ bundle exec rspec
688
+ ```
689
+
690
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
691
+
692
+ To install this gem onto your local machine, run:
693
+
694
+ ```bash
695
+ $ bundle exec rake install
696
+ ```
697
+
698
+ ## ๐Ÿงช Testing
699
+
700
+ The gem repository includes a dummy Rails application for development and testing purposes. To run the tests:
701
+
702
+ ```bash
703
+ $ bundle exec rspec
704
+ ```
705
+
706
+ **Note**: The dummy application is only available in the source repository and is not included in the distributed gem.
707
+
708
+ ## ๐Ÿค Contributing
709
+
710
+ Bug reports and pull requests are welcome on GitHub at https://github.com/IstvanMs/reactive-actions.
711
+
712
+ ## ๐Ÿ“„ License
713
+
714
+ The gem is available as open source under the terms of the MIT License.