From 5ef98b6a0b8fd49989dc7ffe50295c20cc59ed02 Mon Sep 17 00:00:00 2001 From: Hoda Salim Date: Mon, 11 May 2026 10:32:27 +0300 Subject: [PATCH 1/3] Bump version to 1.1.0 and update changelog Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Hoda Salim --- CHANGELOG.md | 12 ++++++++++++ lib/sift/version.rb | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9291ec1..4f3214e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ ## Unreleased +## 1.1.0 + +- Add support for Rails 7.1, 7.2, and 8.0 (#67) +- Migrate CI from Travis to GitHub Actions; test matrix covers Ruby 2.7–3.3 against Rails 7.0–8.0 (#67) +- Fix boolean filter being silently skipped when the value is `false` (#58). Note: filters with empty-string values are now applied (previously skipped); review consumers if you relied on the old behavior. +- Fix `NameError` in JSONB filtering when value is an Array (#56) +- Reorganize documentation into a `docs/` directory (#68) + +### Breaking changes: +- Drop support for Rails 6.1 / ActiveRecord 6.1 +- Require `activerecord >= 7.0` + ## 1.0.0 - Bump version to 1.0.0, making it an official release diff --git a/lib/sift/version.rb b/lib/sift/version.rb index 5eceb55..af73d8d 100644 --- a/lib/sift/version.rb +++ b/lib/sift/version.rb @@ -1,3 +1,3 @@ module Sift - VERSION = "1.0.1".freeze + VERSION = "1.1.0".freeze end From aafb1bffbbc21ccb48361812679431d5dbc5cc1b Mon Sep 17 00:00:00 2001 From: Hoda Salim Date: Mon, 11 May 2026 11:13:44 +0300 Subject: [PATCH 2/3] Remove unused CircleCI SonarQube stub The stub was added in #67 only to satisfy a required branch-protection check left over from when sift lived under the procore org. SonarQube isn't actually configured for this repo and no other procore-oss Ruby gem has SonarQube. Removing the file requires the corresponding required check to be removed from branch protection on main. Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Hoda Salim --- .circleci/config.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 0dd2f88..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,17 +0,0 @@ -version: 2.1 - -jobs: - sonarqube_analysis: - docker: - - image: cimg/ruby:3.3 - steps: - - checkout - - run: - name: Skip SonarQube for open source gem - command: echo "SonarQube analysis skipped - not configured for this repository" - -workflows: - version: 2 - build: - jobs: - - sonarqube_analysis From 36ce9ffd6859600b2e6df457ef4f106d51207ebb Mon Sep 17 00:00:00 2001 From: Hoda Salim Date: Mon, 29 Jun 2026 15:16:20 +0300 Subject: [PATCH 3/3] Document allow_nil and JSONB date range filters Add docs and changelog entries for the allow_nil IS NULL filtering option (#84) and JSONB key date range filtering (#83), both shipping in the 1.1.0 release. Co-authored-by: Cursor Signed-off-by: Hoda Salim --- CHANGELOG.md | 2 ++ docs/filters.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3214e..0d0c0a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Add support for Rails 7.1, 7.2, and 8.0 (#67) - Migrate CI from Travis to GitHub Actions; test matrix covers Ruby 2.7–3.3 against Rails 7.0–8.0 (#67) +- Add `allow_nil: true` option to `filter_on` to enable `IS NULL` filtering for non-JSONB column types (#84) +- Add support for date range filtering on JSONB keys, using the same `...` range format as other filters (#83) - Fix boolean filter being silently skipped when the value is `false` (#58). Note: filters with empty-string values are now applied (previously skipped); review consumers if you relied on the old behavior. - Fix `NameError` in JSONB filtering when value is an Array (#56) - Reorganize documentation into a `docs/` directory (#68) diff --git a/docs/filters.md b/docs/filters.md index 195448a..ceca33d 100644 --- a/docs/filters.md +++ b/docs/filters.md @@ -154,6 +154,29 @@ end The lambda receives the validator object, which gives you access to the filter value and allows you to add errors using `validator.errors.add(:field_name, "error message")`. +## Filtering on Null Values + +By default, non-JSONB filters cannot match rows where a column is `NULL`. Setting `allow_nil: true` on a filter lets consumers opt in to `IS NULL` filtering by passing the string `null` as the filter value. + +```ruby +class PostsController < ApplicationController + include Sift + + filter_on :assignee_id, type: :int, allow_nil: true +end +``` + +With `allow_nil: true`: + +- `?filters[assignee_id]=null` produces `WHERE assignee_id IS NULL` +- `?filters[assignee_id][]=null&filters[assignee_id][]=5` combines the null check with the other values, producing `WHERE assignee_id IS NULL OR assignee_id IN (5)` + +The `null` value is case-insensitive, so `null` and `NULL` behave identically. + +Filters without `allow_nil: true` are unaffected: `null` is treated as an ordinary value and validated against the filter's type (for example, an `int` filter returns a `400` validation error). + +> JSONB columns already support null filtering without this option — see [Filter on JSONB Column](#filter-on-jsonb-column). + ## Filter on JSONB Column Usually JSONB columns stores values as an Array or an Object (key-value), in both cases the parameter needs to be sent in a JSON format. @@ -199,6 +222,20 @@ Will return records with next values stored in the JSONB column `metadata`: { data_1: {another: 'information'} } # When the JSONB key "data_2" is not set. ``` +### Filtering JSONB Keys on Date Ranges + +JSONB key values support date ranges using the same `...` separator as other [range filters](#filter-on-ranges). Pass a range string as the value for a key: + +- `?filters[metadata]={"published_at":"2018-01-01...2018-01-02"}` + +This extracts the key and produces a `BETWEEN` condition: + +```sql +metadata->>'published_at' BETWEEN '2018-01-01' AND '2018-01-02' +``` + +The bounds are parsed as dates when possible and fall back to the raw string otherwise, matching the behavior of the top-level `datetime` range filter. + ## Filter on JSON Array `int` type filters support sending the values as an array in the URL Query parameters. For example `?filters[id]=[1,2]`. This is a way to keep payloads smaller for GET requests. When URI encoded this will become `filters%5Bid%5D=%5B1,2%5D` which is much smaller the standard format of `filters%5Bid%5D%5B%5D=1&&filters%5Bid%5D%5B%5D=2`.