Does Ransack Support PostgreSQL JSON and Array Columns? Complete Guide

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, the constructor sets the @wants_array instance variable based on the predicate type:


# 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 checks the wants_array flag:


# 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:


# 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:

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:


# 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:

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:


# 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:

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:

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:


# 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 and validate arity in 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 and 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 in the activerecord-hackery/ransack repository. This documentation covers both array and JSON/JSONB querying patterns with additional examples beyond the core implementation details.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →