# How to Handle Blank Values and Edge Cases in Ransack Searches

> Learn Ransack search edge cases. Discover how to handle blank values and NULL columns using the _blank predicate for efficient SQL generation.

- Repository: [ActiveRecord Hackery/ransack](https://github.com/activerecord-hackery/ransack)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Ransack automatically strips blank parameters during `Search` object initialization and provides a dedicated `_blank` predicate to explicitly query for NULL or empty columns, preventing unwanted SQL generation.**

The [activerecord-hackery/ransack](https://github.com/activerecord-hackery/ransack) library includes sophisticated logic to handle blank values and other edge cases in Ransack searches across its node hierarchy. Understanding these mechanisms ensures your filtering interfaces degrade gracefully when users submit empty forms, while still allowing explicit queries for missing data.

## How Ransack Automatically Removes Blank Parameters

When you initialize a `Ransack::Search` object, the library immediately sanitizes the input hash to eliminate values that would generate meaningless SQL predicates.

### Parameter Sanitization in Search Objects

In [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb) (lines 27–30), the constructor duplicates your parameters and strips whitespace if the `strip_whitespace` option is enabled (the default). It then rejects any key-value pair where the value is completely blank using the guard:

```ruby
[ *v ].all?{ |i| i.blank? && i != false }

```

This expression wraps single values in an array and verifies that every element is blank, while explicitly preserving `false` values through the `i != false` check. Consequently, empty strings, `nil`, and arrays containing only blanks are removed before the Search object builds its Arel tree.

### Preserving Boolean False Values

The blank-detection logic specifically guards against removing `false` values. Because the validation block checks `i != false`, an explicit `false` in your search parameters—critical for boolean column filtering—is retained and passed through to the predicate builders.

## Using the `_blank` Predicate for NULL Queries

Beyond silently dropping blanks, Ransack exposes a dedicated predicate to explicitly search for empty or NULL columns without writing custom SQL.

### The Blank Predicate Implementation

In [`lib/ransack/constants.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/constants.rb) (lines 136–142), Ransack registers a boolean predicate named **`blank`**. Its Arel mapping uses `EQ_ANY` when the supplied boolean is truthy and `NOT_EQ_ALL` when falsy, allowing you to query:

- `field_blank: true` — matches records where the column is NULL or empty string
- `field_blank: false` — matches records where the column is NOT NULL and not empty

The predicate validates input against `BOOLEAN_VALUES.include?`, ensuring only `true` or `false` are accepted.

## Handling Edge Cases Across Node Types

Ransack's blank-handling strategy extends through its node hierarchy to prevent malformed SQL at every stage of query construction.

### Multi-Parameter Date Attributes

Rails date_select helpers send parameters like `birthday(1i)`, `birthday(2i)`, and `birthday(3i)`. In [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb) (lines 63–86), the `collapse_multiparameter_attributes!` method detects these segmented keys. If any component is blank, the method intelligently drops those components or returns `nil` for the entire date, preventing partial date construction that would otherwise yield invalid SQL comparisons.

### Empty Arrays and IN Clauses

When you pass an empty array to a predicate like `ids_in: []`, Ransack prevents the database error that would result from `IN ()` syntax. Both [`lib/ransack/nodes/grouping.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/grouping.rb) (line 165) and [`lib/ransack/nodes/condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/condition.rb) (line 281) filter their sub-elements by rejecting blank values:

```ruby
.reject { |e| e[1].blank? }

```

This pruning occurs before the Arel tree generates SQL, silently removing the condition rather than executing an empty set comparison.

### Sort Node Protection

The sorting mechanism in [`lib/ransack/nodes/sort.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/sort.rb) (line 11) includes an early return if the raw sort string is blank. This prevents the generation of empty `ORDER BY` clauses that would cause SQL syntax errors when users submit sort forms without selecting a column.

### Value Node Casting

In [`lib/ransack/nodes/value.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/value.rb) (line 5), the `Value` node delegates `blank?` and `present?` to the underlying Ruby object. This delegation allows casting helpers like `cast_to_integer` and `cast_to_float` to recognize blank inputs and return `nil` appropriately, ensuring type coercion does not accidentally convert empty strings to zero or other unintended default values.

## Practical Code Examples

### Filtering for Blank Columns

Use the `_blank` predicate to find records with empty or NULL email addresses:

```ruby
User.ransack(email_blank: true).result

```

Internally, this invokes the `blank` predicate defined in [`constants.rb`](https://github.com/activerecord-hackery/ransack/blob/main/constants.rb), generating SQL that checks for both NULL and empty string conditions using the `EQ_ANY` mapping.

### Automatic Parameter Cleaning

Blank values are stripped automatically during Search initialization:

```ruby
params = { name_cont: '  ', age_eq: '' }
search = User.ransack(params) # Empty values removed at lines 27-30 of search.rb

search.result # Returns all users, no WHERE clause added

```

The whitespace-only string `'  '` is stripped to `''` and subsequently removed, while the empty string for `age_eq` is discarded entirely.

### Excluding Blank Values

To find users with a populated first name and specific age:

```ruby
User.ransack(first_name_blank: false, age_eq: 30).result

```

This generates `WHERE "users"."first_name" IS NOT NULL AND "users"."first_name" <> ''` via the `NOT_EQ_ALL` mapping defined in the blank predicate.

### Handling Empty Arrays

Passing an empty array does not raise a database error:

```ruby
User.ransack(ids_in: []).result # Condition pruned, returns all records

```

The blank detection in [`search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/search.rb) and the grouping/condition pruning logic ensure no `IN ()` syntax error reaches the database.

### Multi-Parameter Date Handling

When date components are partially blank, Ransack collapses them safely:

```ruby

# birthday(2i) and birthday(3i) are empty

User.ransack(birthday(1i): '2024', birthday(2i): '', birthday(3i): '')

# Results in proper Date object construction or nil, not malformed SQL

```

The `collapse_multiparameter_attributes!` routine handles the blank middle and day components without constructing invalid date ranges.

## Summary

- **Automatic sanitization**: In [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb), blank parameters (empty strings, nil, whitespace) are stripped at initialization to prevent empty `WHERE` clauses.
- **Boolean preservation**: The blank detection logic explicitly keeps `false` values, ensuring boolean filters generate correct SQL predicates.
- **Explicit blank queries**: Use the `_blank` predicate (defined in [`lib/ransack/constants.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/constants.rb)) to query for NULL or empty columns using `EQ_ANY` and `NOT_EQ_ALL` Arel mappings.
- **Empty array safety**: [`lib/ransack/nodes/grouping.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/grouping.rb) and [`condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/condition.rb) prune blank conditions, preventing syntax errors from empty `IN ()` clauses.
- **Date parameter handling**: The `collapse_multiparameter_attributes!` method in [`search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/search.rb) safely manages partial date inputs from Rails form helpers.

## Frequently Asked Questions

### Does Ransack remove empty strings from search parameters?

Yes. In [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb) (lines 27–30), Ransack duplicates and inspects all parameters, removing any where the value is blank according to the `[ *v ].all?{ |i| i.blank? && i != false }` check. This includes empty strings, `nil`, and whitespace-only strings when `strip_whitespace` is enabled.

### How do I search for records where a column is NULL or empty?

Use the `_blank` predicate registered in [`lib/ransack/constants.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/constants.rb) (lines 136–142). Pass `field_blank: true` to find records where the column is NULL or an empty string, or `field_blank: false` to exclude them. This generates the appropriate `EQ_ANY` or `NOT_EQ_ALL` Arel constraints.

### Will Ransack ignore false values in my search parameters?

No. The blank detection logic specifically guards against removing `false` through the `i != false` condition in the validation block. This ensures that boolean searches like `active_eq: false` are preserved and generate the correct SQL predicates.

### How does Ransack prevent empty IN clause errors?

When you pass an empty array to a predicate like `ids_in: []`, Ransack prunes this condition in [`lib/ransack/nodes/grouping.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/grouping.rb) (line 165) and [`lib/ransack/nodes/condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/condition.rb) (line 281) by rejecting blank sub-elements. This prevents the generation of invalid `IN ()` SQL syntax.