interactor-validation 0.3.8 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 337f8200b44c78cb5a2eeefa3d9dcd5c5c1ec864ef7f0e18d710309365b21e9f
4
- data.tar.gz: 4c0b74a6a2cc0fbc9bd391665da07a454054c7ec29fef12d84dccd6945296ba3
3
+ metadata.gz: f9c7888fc968eb40b00dbb2225455cd34f60444dfa710eb2d2e3ca991178a572
4
+ data.tar.gz: 2ff3d6b998b0bc1ec4112c888c7169842335f4829fd215b40e08b98e7e6a38a6
5
5
  SHA512:
6
- metadata.gz: b3fc4532523214b0723c009ed73b2d75ad5213480ae920261da7263adf2b3929ecef608b1d6b8924461f0fc873cf11777a2f80ea32528a9c8228320025086440
7
- data.tar.gz: f58f08c52ef1e58be7d8ddb566d14b8aff8b24c408f1976128decada786ce29570ac38d6df7a862e50f5681e64e3ed9eb73b65fb6909da80504f3b113f28c06b
6
+ metadata.gz: 622c1af2f52477ccef49d4fea329a2d27d34b4a9cf30387a5c213ad58c7ae0ee8f645a942cde0dc12e2605128c607a204a1d44d7c54004c4205f27a6a3745107
7
+ data.tar.gz: 57adf88f0a34b152a3af76afdcce71b183dc0e5ef4d79b4bf2ccde88c4dc5cbc15173a2c1e5a257674487b0367ce29261cd721e483a333ac255ca31e5604db59
data/README.md CHANGED
@@ -365,6 +365,9 @@ Interactor::Validation.configure do |config|
365
365
  # Stop at first error for better performance
366
366
  config.halt = false # Set to true to stop on first validation error
367
367
 
368
+ # Skip custom validate! hook when parameter validation fails
369
+ config.skip_validate = true # Set to false to always run validate! hook
370
+
368
371
  # Security settings
369
372
  config.regex_timeout = 0.1 # Regex timeout in seconds (ReDoS protection)
370
373
  config.max_array_size = 1000 # Max array size for nested validation
@@ -476,6 +479,75 @@ end
476
479
  - Improve API response times by failing fast
477
480
  - Provide cleaner error messages (only the most relevant error)
478
481
 
482
+ ### Skip Custom Validations on Parameter Errors
483
+
484
+ Control whether custom `validate!` hooks run when parameter validation fails:
485
+
486
+ ```ruby
487
+ # Default behavior (skip_validate = true)
488
+ class CreateUser
489
+ include Interactor
490
+ include Interactor::Validation
491
+
492
+ configure_validation do |config|
493
+ config.skip_validate = true # Default
494
+ end
495
+
496
+ params :username, :email
497
+
498
+ validates :username, presence: true
499
+ validates :email, presence: true
500
+
501
+ def validate!
502
+ # This will NOT run if username or email validation fails
503
+ # Improves performance by skipping expensive checks
504
+ user_exists = User.exists?(username: username)
505
+ errors.add(:username, "already taken") if user_exists
506
+ end
507
+
508
+ def call
509
+ User.create!(username: username, email: email)
510
+ end
511
+ end
512
+
513
+ # With skip_validate = false, always run validate!
514
+ class CreateUserAlwaysValidate
515
+ include Interactor
516
+ include Interactor::Validation
517
+
518
+ configure_validation do |config|
519
+ config.skip_validate = false # Run validate! even with param errors
520
+ end
521
+
522
+ params :username, :email
523
+
524
+ validates :username, presence: true
525
+ validates :email, presence: true
526
+
527
+ def validate!
528
+ # This WILL run even if username or email is missing
529
+ # Useful when you need to collect all possible errors
530
+ user_exists = User.exists?(username: username) if username.present?
531
+ errors.add(:username, "already taken") if user_exists
532
+ end
533
+
534
+ def call
535
+ User.create!(username: username, email: email)
536
+ end
537
+ end
538
+ ```
539
+
540
+ **When to use skip_validate = true (default):**
541
+ - Skip expensive database lookups when basic params are invalid
542
+ - Avoid unnecessary API calls when required fields are missing
543
+ - Improve performance in high-traffic endpoints
544
+ - Fail fast with only parameter validation errors
545
+
546
+ **When to use skip_validate = false:**
547
+ - Collect all possible validation errors in a single request
548
+ - Always run business logic validations regardless of param state
549
+ - Provide comprehensive error feedback to users
550
+
479
551
  ### ActiveModel Integration
480
552
 
481
553
  Use ActiveModel's custom validation callbacks:
@@ -5,7 +5,8 @@ module Interactor
5
5
  # Configuration class for interactor validation behavior
6
6
  class Configuration
7
7
  attr_accessor :halt, :regex_timeout, :max_array_size,
8
- :enable_instrumentation, :cache_regex_patterns
8
+ :enable_instrumentation, :cache_regex_patterns,
9
+ :skip_validate
9
10
  attr_reader :error_mode
10
11
 
11
12
  # Backward compatibility alias for halt_on_first_error
@@ -22,6 +23,7 @@ module Interactor
22
23
  @max_array_size = 1000 # Maximum array size for nested validation (memory protection)
23
24
  @enable_instrumentation = false # ActiveSupport::Notifications instrumentation
24
25
  @cache_regex_patterns = true # Cache compiled regex patterns for performance
26
+ @skip_validate = true # Skip validate! hook if validate_params! has errors
25
27
  end
26
28
 
27
29
  def error_mode=(mode)
@@ -146,8 +146,11 @@ module Interactor
146
146
  { attribute: error.attribute, type: :invalid, options: {} }
147
147
  end
148
148
 
149
- # Skip custom validations if halt was requested
150
- unless @halt_validation
149
+ # Skip custom validations if configured to skip when param errors exist
150
+ skip_custom_validation = current_config.skip_validate && existing_error_details.any?
151
+
152
+ # Skip custom validations if halt was requested or if configured to skip on param errors
153
+ unless @halt_validation || skip_custom_validation
151
154
  # Call super to allow class's validate! to run and add custom errors
152
155
  # Rescue exceptions that might be raised
153
156
  begin
@@ -245,7 +248,14 @@ module Interactor
245
248
  # Get the current configuration (instance config overrides global config)
246
249
  # @return [Configuration] the active configuration
247
250
  def current_config
248
- @current_config || self.class.validation_config || Interactor::Validation.configuration
251
+ return @current_config if @current_config
252
+
253
+ # Try to get class-level config if available
254
+ if self.class.respond_to?(:validation_config)
255
+ self.class.validation_config || Interactor::Validation.configuration
256
+ else
257
+ Interactor::Validation.configuration
258
+ end
249
259
  end
250
260
 
251
261
  # Instrument a block of code if instrumentation is enabled
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Interactor
4
4
  module Validation
5
- VERSION = "0.3.8"
5
+ VERSION = "0.3.9"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactor-validation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilson Anciro