The method presence_in
, which is part of ActiveSupport, is used to check if a value is present in a given collection and returns the value if it is present; otherwise, it returns nil
. However, it can also raise an ArgumentError
if the argument does not respond to the include?
method. In this blog post, we will explore the presence_in
method, how it works, and common pitfalls to avoid.
How presence_in
Works
The presence_in
method is designed to simplify the process of checking whether a value exists within a collection. Here’s a simple example:
1
2
3
4
5
6
7
8
9
valid_values = %w( project calendar task )
value = 'calendar'
result = value.presence_in(valid_values)
# result will be 'calendar' because 'calendar' is present in valid_values
value = 'unknown'
result = value.presence_in(valid_values)
# result will be nil because 'unknown' is not present in valid_values
In this example, value.presence_in(valid_values)
returns the value itself if it is found in the valid_values
array, otherwise, it returns nil
.
Practical Usage
A common use case for presence_in
is to validate parameters in a Rails controller:
1
2
3
4
5
6
7
8
9
10
11
class ProjectsController < ApplicationController
def create
bucket_type = params[:bucket_type].presence_in(%w( project calendar task ))
if bucket_type
# Proceed with bucket_type
else
# Handle invalid bucket_type
end
end
end
In this scenario, params[:bucket_type]
is checked against a list of valid bucket types. If it is found in the list, it proceeds; otherwise, it handles the invalid case.
Avoiding ArgumentError
While presence_in
is very useful, it can raise an ArgumentError
if the argument passed does not respond to the include?
method. Let’s look at an example that would cause this error:
1
2
3
4
5
6
7
params[:bucket_type] = 'calendar'
# Suppose we pass an object that does not respond to the `include?` method
invalid_collection = 12345
# This will raise an ArgumentError because 12345 does not respond to `include?`
result = params[:bucket_type].presence_in(invalid_collection)
In this example, invalid_collection
is an integer, which does not respond to the include?
method. When you try to use presence_in
with such an argument, Rails raises an ArgumentError
.
Full Example with Error Handling
Here’s a complete script demonstrating both correct usage and error handling:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
params = { bucket_type: 'calendar' }
# Correct usage
valid_values = %w( project calendar task )
result = params[:bucket_type].presence_in(valid_values)
puts result # Outputs 'calendar'
# Incorrect usage leading to ArgumentError
invalid_collection = 12345
begin
result = params[:bucket_type].presence_in(invalid_collection)
rescue ArgumentError => e
puts "Error captured: #{e.message}" # Outputs 'Error captured: argument doesn’t respond to #include?'
end
The presence_in
method is a handy tool for checking the presence of a value within a collection in Ruby on Rails. However, it’s important to ensure that the argument passed is a valid collection that responds to the include?
method to avoid unexpected errors.