[#119637] Behavior of raising from rescue blocks when multiple rescue blocks exist — Rodrigo Rosenfeld Rosas via ruby-core <ruby-core@...>
Hello, I couldn't find any documentation about the subject, so I thought
3 messages
2024/10/29
[ruby-core:119607] [Ruby master Feature#20812] Proposal for Safe Include Method in Ruby
From:
"jeremyevans0 (Jeremy Evans) via ruby-core" <ruby-core@...>
Date:
2024-10-24 13:10:23 UTC
List:
ruby-core #119607
Issue #20812 has been updated by jeremyevans0 (Jeremy Evans).
rogerconsul (Roger Consul) wrote:
> The current `include?` method raises an error when passed `nil` as an argument.
Are you sure?
```ruby
# No Error
[1, 2].include?(nil)
[Object.new].include?(nil)
# Error, but due to custom ==, not include?
o = Object.new
def o.==(v) = (raise unless v)
[o].include?(nil)
```
Maybe you are using some core extension that causes `include?` to raise an error if given `nil`? Can you provide a self-contained reproducible example that shows `include?` raising if the argument is `nil`?
----------------------------------------
Feature #20812: Proposal for Safe Include Method in Ruby
https://bugs.ruby-lang.org/issues/20812#change-110228
* Author: rogerconsul (Roger Consul)
* Status: Open
----------------------------------------
# Proposal for Safe Include Method in Ruby
## Description
Add a new method `include_safe?` to Ruby's `Enumerable` module that safely handles nil arguments in inclusion checks.
## Problem Statement
The current `include?` method raises an error when passed `nil` as an argument. This requires developers to write defensive code with explicit nil checks, leading to less readable and more error-prone code.
```ruby
# Current problematic scenarios:
collection.include?(nil) # Works, checks for nil in collection
collection.include?(value) # Raises error if value is nil
# Current workarounds:
value && collection.include?(value)
collection.include?(value.to_s)
```
## Proposed Solution
Add `include_safe?` method that returns `false` when the argument is `nil`:
```ruby
module Enumerable
def include_safe?(obj)
return false if obj.nil?
include?(obj)
end
end
```
### Usage Examples
```ruby
numbers = [1, 2, 3]
document_id = nil
# Current approach
document_id && numbers.include?(document_id) # false
# Proposed approach
numbers.include_safe?(document_id) # false
# Works normally for non-nil values
numbers.include_safe?(2) # true
numbers.include_safe?(4) # false
# Edge cases handled
[nil].include_safe?(nil) # false
[].include_safe?(nil) # false
```
## Benefits
1. **Improved Safety**: Eliminates a common source of runtime errors
2. **Better Readability**: Removes need for explicit nil checks
3. **Consistent Behavior**: Provides predictable handling of nil values
4. **Rails Alignment**: Similar to Rails' safe navigation patterns
5. **Reduced Boilerplate**: Eliminates common defensive coding patterns
## Implementation Notes
This would be implemented in C as part of Ruby's core, but here's a Ruby reference implementation:
```ruby
module Enumerable
def include_safe?(obj)
return false if obj.nil?
include?(obj)
end
end
```
## Testing Strategy
```ruby
require 'minitest/autorun'
class TestIncludeSafe < Minitest::Test
def setup
@array = [1, 2, 3]
@array_with_nil = [1, nil, 3]
end
def test_basic_inclusion
assert @array.include_safe?(1)
refute @array.include_safe?(4)
end
def test_nil_handling
refute @array.include_safe?(nil)
refute @array_with_nil.include_safe?(nil)
end
def test_empty_collection
refute [].include_safe?(nil)
refute [].include_safe?(1)
end
end
```
## Alternative Considerations
1. **Name Alternatives**:
- `try_include?`
- `safe_include?`
- `includes_safely?`
2. **Alternative Approaches**:
- Modify existing `include?` behavior (rejected due to backward compatibility)
- Add parameter to existing `include?` (rejected for clarity)
## Impact Analysis
### Positive Impact
- Reduces runtime errors
- Improves code readability
- Follows principle of least surprise
### Potential Concerns
- Another method to learn
- Possible confusion with regular `include?`
## Similar Features in Ruby
- Safe navigation operator (`&.`)
- `try` method in Rails
- `fetch` method with default value
## Backward Compatibility
This change is fully backward compatible as it introduces a new method without modifying existing behavior.
## Reference Implementation
A gem implementing this feature is available at: [Link to gem if created]
## Questions for Core Team
1. Is `include_safe?` the best name for this method?
2. Should this be added to `Array` specifically rather than `Enumerable`?
3. Should we consider any additional edge cases?
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/