# Does Ransack Support PostgreSQL JSON and Array Columns? Complete Guide

> Learn how Ransack fully supports PostgreSQL JSON and array columns using built-in predicates and native PostgreSQL operators for powerful searching. Get the complete guide.

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

---

**Yes, Ransack fully supports PostgreSQL arrays, JSON, and JSONB columns through built-in array predicates and extensible ransacker methods that generate native PostgreSQL operators like `@>`.**

Ransack provides a flexible search interface for Active Record models, and according to the activerecord-hackery/ransack source code, it handles PostgreSQL-specific data types without requiring external extensions. Whether you're querying integer arrays or searching within JSONB documents, the library's predicate system offers both native compatibility and custom extension points.

## Native Array Support with the wants_array Flag

PostgreSQL array columns work seamlessly with Ransack's collection-based predicates. The implementation relies on a specific flag set during predicate initialization.

In [`lib/ransack/predicate.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/predicate.rb), the constructor sets the `@wants_array` instance variable based on the predicate type:

```ruby

# lib/ransack/predicate.rb (lines 43-45)

@wants_array = opts.fetch(:wants_array,
  @compound || Constants::IN_NOT_IN.include?(@arel_predicate))

```

This flag indicates that the predicate expects an array of values rather than a single scalar. When you use predicates like `*_in`, `*_any`, or `*_all`, Ransack automatically configures them to accept arrays.

## Array Validation in Ransack::Nodes::Condition

Before generating SQL, Ransack validates that the supplied values match the predicate's expected arity. The `valid_arity?` method in [`lib/ransack/nodes/condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/condition.rb) checks the `wants_array` flag:

```ruby

# lib/ransack/nodes/condition.rb (lines 72-74)

def valid_arity?
  values.size <= 1 || predicate.wants_array
end

```

This validation allows array values to pass through when the predicate sets `wants_array = true`, while restricting other predicates to single values.

## Querying JSON and JSONB Columns

Ransack handles JSON data through two primary patterns: **ransackers** for fixed-key extraction and **custom predicates** for containment operations.

### Searching Fixed JSON Keys with Ransackers

For predictable JSON schemas, define a ransacker that extracts the specific key using PostgreSQL's JSON operators:

```ruby

# app/models/product.rb

class Product < ApplicationRecord
  ransacker :color do |parent|
    Arel.sql("products.specs ->> 'color'")
  end
end

```

This creates a searchable attribute that maps to the SQL expression `products.specs ->> 'color'`, allowing standard predicates:

```ruby
Product.ransack(color_eq: 'red').result

# Generates: WHERE (products.specs ->> 'color') = 'red'

```

### Custom Predicates for JSON Containment

To use PostgreSQL's `@>` (contains) operator for JSONB columns, register a custom predicate in your initializer:

```ruby

# config/initializers/ransack.rb

Ransack.configure do |config|
  config.add_predicate 'jcont', 
    arel_predicate: 'contains', 
    formatter: proc { |v| JSON.parse(v) }
end

```

Now you can query JSONB containment:

```ruby
User.ransack(metadata_jcont: '{"role":"admin"}').result

# Generates: WHERE "users"."metadata" @> '{"role":"admin"}'

```

## Practical Implementation Examples

Here are complete implementations for common PostgreSQL search scenarios.

### 1. Querying Integer Arrays

Search for records where an array column contains any of the specified values:

```ruby

# Assuming tags is an integer[] column

Article.ransack(tags_id_in: [2, 5, 7]).result

# Generates: WHERE "articles"."tags_id" IN (2, 5, 7)

```

Or using the contains operator for array overlap:

```ruby
Article.ransack(tags_contains: [2, 5]).result

# Generates: WHERE "articles"."tags" @> ARRAY[2,5]

```

### 2. JSONB Key Search via Ransacker

Extract and search nested JSON values:

```ruby
class Contact < ApplicationRecord
  ransacker :city do |parent|
    Arel.sql("contacts.data ->> 'city'")
  end
end

Contact.ransack(city_eq: 'Berlin').result

```

### 3. Advanced JSONB Containment

Combine custom predicates with the ActiveRecordExtended gem for complex JSONB queries:

```ruby

# Requires ActiveRecordExtended for Arel.contains support

Ransack.configure do |config|
  config.add_predicate(
    'jcont',
    arel_predicate: 'contains',
    formatter: proc { |v| JSON.parse(v) }
  )
end

# Search for users with specific metadata

User.ransack(metadata_jcont: '{"active":true,"plan":"pro"}').result

```

## Summary

- **Array columns**: Fully supported via built-in predicates (`*_in`, `*_any`) that set `wants_array = true` in [`lib/ransack/predicate.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/predicate.rb) and validate arity in [`lib/ransack/nodes/condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/condition.rb).
- **JSON/JSONB fixed keys**: Use `ransacker` blocks with PostgreSQL JSON operators (`->>`, `->`) to create searchable virtual attributes.
- **JSON containment**: Extend Ransack with custom predicates mapping to Arel's `contains` method to leverage the `@>` operator.
- **No external dependencies**: Core array support works without additional gems, while advanced JSON containment requires only standard Arel extensions.

## Frequently Asked Questions

### Does Ransack require additional gems to search PostgreSQL arrays?

No. According to the source code in [`lib/ransack/predicate.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/predicate.rb) and [`lib/ransack/nodes/condition.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/condition.rb), array support is built into the core library through the `wants_array` flag. Predicates like `*_in` and `*_any` handle PostgreSQL arrays natively without requiring configuration changes or external dependencies.

### How do I search inside a JSONB column for a specific key value?

Define a **ransacker** in your model that extracts the JSON key using PostgreSQL's `->>` operator. This creates a virtual attribute you can query with standard predicates like `eq` or `cont`. For example, `ransacker :city { Arel.sql("table.column ->> 'city'") }` allows `city_eq: 'Paris'` queries.

### Can Ransack use PostgreSQL's JSON containment operator (`@>`)?

Yes, but you must configure a custom predicate. Add a predicate via `Ransack.configure` that sets `arel_predicate: 'contains'` and includes a formatter to parse JSON strings. This maps to the `@>` operator in generated SQL, enabling efficient JSONB document searches.

### Where is PostgreSQL-specific documentation located in the Ransack repository?

The official guide for PostgreSQL features resides at [`docs/docs/going-further/searching-postgres.md`](https://github.com/activerecord-hackery/ransack/blob/main/docs/docs/going-further/searching-postgres.md) in the activerecord-hackery/ransack repository. This documentation covers both array and JSON/JSONB querying patterns with additional examples beyond the core implementation details.