activerecord-hackery/ransack
Object-based searching.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2mo ago
- ✓35+ active contributors
- ✓Distributed ownership (top contributor 19% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/activerecord-hackery/ransack)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/activerecord-hackery/ransack on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: activerecord-hackery/ransack
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/activerecord-hackery/ransack shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 2mo ago
- 35+ active contributors
- Distributed ownership (top contributor 19% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live activerecord-hackery/ransack
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/activerecord-hackery/ransack.
What it runs against: a local clone of activerecord-hackery/ransack — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in activerecord-hackery/ransack | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 96 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of activerecord-hackery/ransack. If you don't
# have one yet, run these first:
#
# git clone https://github.com/activerecord-hackery/ransack.git
# cd ransack
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of activerecord-hackery/ransack and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "activerecord-hackery/ransack(\\.git)?\\b" \\
&& ok "origin remote is activerecord-hackery/ransack" \\
|| miss "origin remote is not activerecord-hackery/ransack (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "lib/ransack.rb" \\
&& ok "lib/ransack.rb" \\
|| miss "missing critical file: lib/ransack.rb"
test -f "lib/ransack/context.rb" \\
&& ok "lib/ransack/context.rb" \\
|| miss "missing critical file: lib/ransack/context.rb"
test -f "lib/ransack/adapters/active_record/context.rb" \\
&& ok "lib/ransack/adapters/active_record/context.rb" \\
|| miss "missing critical file: lib/ransack/adapters/active_record/context.rb"
test -f "lib/polyamorous/join_dependency.rb" \\
&& ok "lib/polyamorous/join_dependency.rb" \\
|| miss "missing critical file: lib/polyamorous/join_dependency.rb"
test -f "lib/ransack/helpers/form_helper.rb" \\
&& ok "lib/ransack/helpers/form_helper.rb" \\
|| miss "missing critical file: lib/ransack/helpers/form_helper.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 96 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~66d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/activerecord-hackery/ransack"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Ransack is a Ruby gem that adds object-based search functionality to Rails applications without external dependencies like Elasticsearch. It translates Ruby search objects into SQL queries, enabling users to build complex WHERE/ORDER BY clauses through a declarative DSL—no raw SQL or query string manipulation needed. Ransack is a monolithic gem (not a monorepo). The lib/ directory contains core search logic, app/ likely holds Rails integration (view helpers, controllers), and spec/ houses the test suite. Documentation is a separate Docusaurus project under docs/ with markdown files for tutorials, API guides, and advanced features—this is published as GitHub Pages, not bundled with the gem.
👥Who it's for
Rails developers building search features who want to avoid external search infrastructure (Elasticsearch, Algolia) and keep search logic in Ruby. Particularly useful for CRUD apps, admin dashboards, and e-commerce sites where SQL-backed search suffices and operational simplicity is valued.
🌱Maturity & risk
Highly mature and production-ready. Ransack is an established project with 305KB of Ruby code, extensive test coverage (implied by CI/CD setup), active GitHub Actions workflows (codeql, test, deploy), and comprehensive Docusaurus documentation. Supported officially for Rails 8.1/8.0/7.2 on Ruby 3.1+, indicating ongoing maintenance alignment with modern Rails.
Low risk for standard use cases; minimal external dependencies (Rails only). However, check the main branch for unreleased breaking changes (v3.0.0 exists per changelog). Single points of concern: custom predicate extensions could break across versions, and SQL injection is possible if user input bypasses Ransack's sanitization (see security guidelines in .github/SECURITY.md). No indication of single-maintainer risk from available data.
Active areas of work
Active maintenance: v3.0.0 was released (per CHANGELOG.md blog post 2022-03-27), modern CI/CD via GitHub Actions (test.yml, deploy.yml, codeql.yml, rubocop.yml for linting), and ongoing documentation expansion. The repository supports the latest Rails/Ruby versions and accepts contributions via pull requests with test coverage expectations.
🚀Get running
Clone, install, and test locally:
git clone https://github.com/activerecord-hackery/ransack.git
cd ransack
bundle install
bundle exec rake test
For documentation development, navigate to docs/ and run npm install && npm start (Node.js required for Docusaurus).
Daily commands:
Gem development: bundle exec rake test (run full test suite). Documentation locally: cd docs && npm install && npm start (launches Docusaurus on http://localhost:3000). Rubocop linting: bundle exec rubocop (enforced in CI).
🗺️Map of the codebase
lib/ransack.rb— Main entry point that loads the entire Ransack gem and sets up the DSL for object-based searchinglib/ransack/context.rb— Core abstraction managing search context, attribute resolution, and predicate application—every search request flows through thislib/ransack/adapters/active_record/context.rb— ActiveRecord-specific context implementation that translates Ransack searches into Arel SQL querieslib/polyamorous/join_dependency.rb— Handles complex JOIN operations for associated record searches—critical for multi-table querieslib/ransack/helpers/form_helper.rb— Provides Rails form helpers to generate search UI; primary touch point for view-layer integrationlib/ransack/configuration.rb— Global configuration system controlling predicate definitions, i18n, and search behavior across the gemCHANGELOG.md— Historical record of breaking changes and feature additions—essential context for upgrade paths
🛠️How to make changes
Add a Custom Predicate
- Define the predicate in an initializer using Ransack::Configuration (
lib/ransack/configuration.rb) - Implement the predicate logic as a method that returns an Arel node (
lib/ransack/adapters/active_record/context.rb) - Add i18n translations for the predicate name in your locale file (
lib/ransack/locale/ar.yml)
Add a Custom Ransacker (Searchable Attribute)
- In your model, use ransacker(:attribute_name) DSL to define a custom searchable column (
lib/ransack/adapters/active_record/base.rb) - Use the context to resolve the ransacker into an Arel node (
lib/ransack/adapters/active_record/context.rb) - Test via form_helper or direct .ransack() calls (
lib/ransack/helpers/form_helper.rb)
Extend Search to Polymorphic Associations
- Define polymorphic reflection in the model using has_one/has_many :as (
lib/polyamorous/activerecord/reflection.rb) - Let polyamorous build JOIN paths for the polymorphic types (
lib/polyamorous/join_dependency.rb) - Query via search_form_for with nested condition builder in view (
lib/ransack/helpers/form_builder.rb)
Add Form Customization
- Create a custom form builder inheriting from Ransack::Helpers::FormBuilder (
lib/ransack/helpers/form_builder.rb) - Override field rendering methods (predicate_select_for, attribute_select_for, etc.) (
lib/ransack/helpers/form_helper.rb) - Pass your custom builder class to search_form_for(:builder => YourBuilder) (
docs/docs/going-further/form-customisation.md)
🔧Why these technologies
- Arel (Abstract Relational Engine) — Provides vendor-agnostic SQL query building; decouples Ransack from raw SQL strings and database-specific syntax
- Polyamorous (custom gem included) — Extends ActiveRecord's JOIN dependency to support polymorphic associations and complex nested joins that standard ActiveRecord cannot handle
- Rails form helpers (ERB + FormBuilder) — Seamless integration with Rails conventions; allows developers to drop search forms into existing templates without a separate JavaScript framework
- i18n (Rails built-in) — Provides out-of-the-box translation for predicate names and error messages across 20+ languages
- Docusaurus (docs site) — React-based static site for comprehensive, searchable documentation; decouples docs from gem versioning and enables multiple language support
⚖️Trade-offs already made
-
Included Polyamorous gem instead of relying on ActiveRecord's associations
- Why: Standard ActiveRecord cannot represent polymorphic JOINs or complex reflection chains required for advanced searches
- Consequence: Added ~50KB to gem size and maintenance burden; enables powerful searches that would otherwise require Elasticsearch
-
Server-side search only (no client-side indexing)
- Why: Targets mid-market Rails apps that don't need real-time full-text search at scale
- Consequence: Not suitable for massive datasets (100M+ records) or sub-millisecond latency requirements; users should migrate to Elasticsearch for that tier
-
Predicates are database-specific, not abstracted
- Why: Maximizes query efficiency by using native database operators (e.g., PostgreSQL's @> for JSON, MySQL's LIKE BINARY)
- Consequence: Search behavior may vary across databases; test suite must cover all supported adapters
-
Form helpers generate HTML5 inputs (not JavaScript widgets)
- Why: Keeps the gem zero-dependency and frontend-agnostic; works in any Rails view without npm or build step
- Consequence: No autocomplete, typeahead, or live preview—developers must add these separately via JavaScript
🚫Non-goals (don't propose these)
- Real-time full-text search at scale (> 1M records); users should use Elasticsearch, Algolia, or Solr for that
- JavaScript/TypeScript client SDK; Ransack is server-side only
- Authentication or authorization; Ransack does not control access to searchable attributes—use Pundit or CanCanCan
- Non-relational databases; limited to SQL-based adapters (ActiveRecord only)
- Caching layer or query optimization; Ransack delegates to ActiveRecord query caching and database indexes
🪤Traps & gotchas
SQL Injection via untrusted input: Ransack sanitizes most inputs, but custom ransacker definitions or unvalidated sort parameters can be exploited—always validate user input at the controller layer. Rails version pinning: The .github/workflows/test.yml matrix tests specific Rails/Ruby combos; mismatches may cause silent failures. Predicate naming collisions: Custom predicates can shadow built-ins if not namespaced carefully. N+1 queries on associations: Using includes/joins correctly in your Ransack scope is the developer's responsibility, not automatic. I18n expectations: Predicate labels and error messages expect i18n files under config/locales/ per docs/docs/going-further/i18n.md—missing locales silently fall back to English keys. No significant environment variable requirements noted.
🏗️Architecture
💡Concepts to learn
- Predicate-based filtering — Ransack's core abstraction—predicates like 'cont' (contains), 'gt' (greater than), 'matches' (regex) are mapped to SQL operators; understanding predicates is essential to using Ransack effectively
- Arel (Abstract Relation Language) — Ransack uses Arel nodes under the hood to build SQL queries programmatically rather than string concatenation; familiarity helps debug complex searches and understand query generation
- Ransacker (custom search attribute) — Allows mapping non-database attributes or computed columns into Ransack search scope; essential pattern for searching across joined data or denormalized fields
- Polymorphic associations in search — Ransack supports STI (Single Table Inheritance) and polymorphic belongs_to relationships; critical for complex domain models but requires careful predicate design
- Active Record Scopes + Ransack composition — Ransack searches can be chained with Rails scopes (e.g.,
Post.published.ransack(params[:q]).result); understanding scope precedence prevents unexpected filtering behavior - N+1 query problem in Ransack results — Ransack generates efficient WHERE clauses but doesn't auto-include associations; developers must manually use
.includes()or.joins()to avoid fetching related records in loops
🔗Related repos
activerecord-hackery/kaminari— Pagination gem frequently paired with Ransack for paginated search results in Rails appsheartcombo/devise— Authentication gem often used alongside Ransack in admin dashboards and user management interfacespresidentbeef/brakeman— Security scanner specifically audits Rails code for SQL injection vulnerabilities, critical for validating Ransack implementationsrails/rails— Core Rails repository; Ransack depends on Active Record and Arel, so Rails updates can affect compatibilityelastic/elasticsearch-rails— Direct alternative for full-text and complex search needs; understanding both helps teams choose the right tool
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add missing documentation for polymorphic search with code examples
The file docs/docs/going-further/polymorphic-search.md exists but is likely incomplete. Ransack's polymorphic search is a complex feature that many users struggle with. Adding detailed examples showing how to search across polymorphic associations (with working code snippets for both model setup and search queries) would significantly reduce support questions and improve adoption.
- [ ] Review existing
docs/docs/going-further/polymorphic-search.mdcontent - [ ] Add complete model setup examples (e.g., searchable polymorphic associations)
- [ ] Include 3-4 real-world search query examples with explanations
- [ ] Add common gotchas and troubleshooting section
- [ ] Link polymorphic-search.md from the main
docs/docs/intro.mdin the appropriate section
Add GitHub Action workflow for dependency security audits
The repo has .github/workflows/codeql.yml, rubocop.yml, and test.yml, but is missing a dedicated workflow for Ruby gem dependency vulnerabilities. Given Ransack's status as a widely-used Rails gem with complex dependencies (@docusaurus, React, etc.), adding bundler-audit or gems vulnerability scanning would catch supply-chain risks early and demonstrate security-first maintenance.
- [ ] Create
.github/workflows/security-audit.ymlthat runsbundle auditon each push/PR - [ ] Configure to fail the check if vulnerabilities are found
- [ ] Add cron job to run daily for proactive detection
- [ ] Document the security workflow in
CONTRIBUTING.md - [ ] Add security badge to
README.mdonce workflow is active
Add integration tests for ransack searches with PostgreSQL-specific features
The file docs/docs/going-further/searching-postgres.md exists, indicating PostgreSQL-specific search functionality (likely full-text search, JSONB, or array operators). However, there's likely no dedicated test suite validating these features work correctly. Adding tests in the main test suite would ensure PostgreSQL-only predicates don't regress and document expected behavior.
- [ ] Audit
docs/docs/going-further/searching-postgres.mdto identify all PostgreSQL predicates documented - [ ] Create new test file
spec/ransack/adapters/postgres_search_spec.rb(or similar structure) - [ ] Write integration tests for each PostgreSQL-specific predicate (e.g.,
@>,<@,@@,@operators) - [ ] Add tests for edge cases (NULL handling, type coercion, combining with standard predicates)
- [ ] Update GitHub Actions
test.ymlto run PostgreSQL tests against a Postgres service container
🌿Good first issues
- Add missing test coverage for the polymorphic search feature (mentioned in docs/docs/going-further/polymorphic-search.md but no spec file visible in the file list). Create spec/ransack/polymorphic_search_spec.rb with test cases for belongs_to :polymorphic associations.: Improves test suite completeness and ensures a documented feature is regression-safe
- Expand docs/docs/going-further/searching-postgres.md with concrete examples of Postgres-specific predicates (jsonb contains, full-text search using
@@ tsquery). Add runnable code snippets showing schema + Ransacker setup.: Closes documentation gap for a common use case that requires Postgres-specific knowledge beyond the main docs - Create a new doc file docs/docs/going-further/debugging-ransack-queries.md with guidance on inspecting generated SQL, logging Arel output, and common predicate mistakes. Reference lib/ransack/search.rb's inspect method.: Onboarding friction point: new users struggle to understand why searches produce unexpected SQL; this guide would save support burden
⭐Top contributors
Click to expand
Top contributors
- @deivid-rodriguez — 19 commits
- @scarroll32 — 17 commits
- @gregmolnar — 13 commits
- @Copilot — 9 commits
- @dependabot[bot] — 9 commits
📝Recent commits
Click to expand
Recent commits
e82f6ba— support enum (#1665) (pekopekopekopayo)4d76089— Add CI with Rails 8.1 and Ruby 3.3.x, 3.4.x and 4.0.1 (#1667) (tatematsu-k)271cb42— Revise CHANGELOG for versioning and support updates (#1648) (scarroll32)383c5dd— Version 4.4.1 (scarroll32)a6875aa— Revert "Fix enum support" (#1645) (scarroll32)0189ed1— Remove Rails 7.1 support (#1585) (Copilot)9995e09— Encourage community to create failing PRs for bugs (#1642) (scarroll32)6f019e0— Replace blueprints with FactoryBot (#1595) (Copilot)3d985fd— Improve test coverage (#1641) (scarroll32)12df393— Release process notes (scarroll32)
🔒Security observations
Ransack is a searching library with inherent complexity in query building that requires careful attention to SQL injection and input validation. The main security concerns are: (1) potential SQL injection risks in dynamic query construction, (2) outdated dependencies in the documentation website, and (3) potential XSS vulnerabilities in result display if not properly escaped. The project has basic security infrastructure (SECURITY.md, CodeQL scanning), but dependency versions need updating and security code review of the core query-building logic is recommended. Regular security audits and dependency scanning should be implemented.
- High · Potential SQL Injection Risk in Search Functionality —
lib/ransack, lib/polyamorous. Ransack is an object-based searching library for Rails that processes user input to build database queries. Given the nature of dynamic query building based on user-supplied search parameters, there is inherent risk of SQL injection if input sanitization is not properly implemented throughout the codebase. The file structure suggests complex query building logic (polyamorous join handling, ransackers) that could be vulnerable. Fix: Conduct a thorough code review of query building logic, ensure parameterized queries are used consistently, implement strict input validation, and review the handling of custom ransackers and predicates. Verify that all user inputs are properly escaped and that raw SQL is avoided. - Medium · Outdated Dependencies in Documentation Website —
docs/package.json. The docs/package.json contains several dependencies with potential security concerns: react@17.0.2 is an older version (current is 18.x+), and the 'trim' package resolution to ^0.0.3 is extremely outdated. These older versions may contain known vulnerabilities. Fix: Update react and react-dom to the latest stable versions (18.x or higher), remove the 'trim' resolution if not specifically required, and audit all dependencies for known CVEs. Run 'npm audit' and address high/critical vulnerabilities. - Medium · Potential XSS Risk in Search Results Display —
View templates and JavaScript (not shown in file structure). While the provided file structure doesn't show view files, Ransack generates and displays search results. If user-supplied search parameters or search results are not properly escaped when rendered in HTML/JavaScript contexts, XSS vulnerabilities could occur. Fix: Ensure all user inputs and dynamic content are properly escaped using Rails helpers (h, sanitize, etc.). Review any custom views or JavaScript that handle search results. Implement Content Security Policy (CSP) headers. - Medium · Insufficient Dependency Pinning —
docs/package.json. The package.json uses caret (^) version constraints which allow minor and patch updates automatically. This could introduce breaking changes or vulnerabilities from transitive dependencies without explicit review. Fix: Consider using more restrictive version pinning (e.g., ~2.2.0 instead of ^2.2.0) for critical dependencies. Generate and review lock files (yarn.lock is present but should be committed). Implement automated dependency scanning in CI/CD pipeline. - Low · Missing Security Headers Configuration —
docs/docusaurus.config.js. No explicit security headers configuration visible in the documentation website setup (docusaurus.config.js not fully reviewed). Common headers like HSTS, X-Content-Type-Options, X-Frame-Options may be missing. Fix: Configure security headers in the Docusaurus config or web server. Add HSTS preload, X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and other recommended security headers. - Low · No Evidence of SECURITY.md Implementation Details —
.github/SECURITY.md. While a SECURITY.md file exists (.github/SECURITY.md), the content is not provided. Best practices require clear vulnerability disclosure procedures and security guidelines. Fix: Ensure SECURITY.md includes: vulnerability reporting procedures, responsible disclosure timeline, security contact information, and any security policies.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.