forest_liana 9.20.7 → 9.20.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed69fd6aba8fea8a03a02738a6f9ca6e75ae334980e501470dbabe1d58c37497
4
- data.tar.gz: a6439711199628972e57f782968244c096566919801510d2193e3d16fbe5d800
3
+ metadata.gz: dfcdfafce741a2f8305f64a7241219a6f9b54227dd310dd7269ff83043f0f35d
4
+ data.tar.gz: c3ce3c647b53d3cc7bd8c5d45ed98c887588112c6e5e7fc558ca6ca5ddf385f2
5
5
  SHA512:
6
- metadata.gz: e6101bb2d0ea3dfe2b3944cdf5d2ca3391ecd26450653517dd30553ffd4075dcb0cb23b6659996303259f6bd931c8054a58986f9337adc5417f94df8f1aac8b2
7
- data.tar.gz: 3de7e6bc1710e6e8f8e1c8b1857775091e7d5d707d57c9f7f4dd1a993c7fbac111e350a88d4623e90357b8815aaf74a1de6a01710c01a81bd039b465ca19f600
6
+ metadata.gz: debd8bdb65d707795b7e895769c3ec1bd1fc0796bc971edfad2d0446a6b19e1b2b78bdd1c64cd77b2dc615eecc5384b868d1e8ab01810646aa287fd8c7c1a1f1
7
+ data.tar.gz: 9534d5fd16d409d282dd806955386e730a428c3c8405b0beb0284bd317f6825a8f5cdf616ca662e4148a8df9703b23e0370772edd9a35d9c6dbca9e5fe72ff76
@@ -83,6 +83,10 @@ module ForestLiana
83
83
  value = condition['value']
84
84
  field_name = condition['field']
85
85
 
86
+ # NOTICE: captured before the enum mapping below, which turns an unknown
87
+ # enum value into nil and would otherwise look like a null filter.
88
+ null_value = value.nil?
89
+
86
90
  if @operator_date_parser.is_date_operator?(operator)
87
91
  field_schema = SchemaUtils.find_column_schema_by_name(ForestLiana.name_for(@resource), field_name)
88
92
  condition = @operator_date_parser.get_date_filter(operator, value, field_schema)
@@ -99,6 +103,14 @@ module ForestLiana
99
103
 
100
104
  case_insensitive = operator == 'i_contains'
101
105
  parsed_field = parse_field_name(field_name, case_insensitive)
106
+
107
+ # NOTICE: the UI sends a null equality filter as a JSON null; `= NULL` and
108
+ # `!= NULL` never match anything in SQL.
109
+ if null_value
110
+ return "#{parsed_field} IS NULL" if operator == 'equal'
111
+ return "#{parsed_field} IS NOT NULL" if operator == 'not_equal'
112
+ end
113
+
102
114
  parsed_operator = parse_operator(operator)
103
115
  parsed_value = parse_value(operator, value)
104
116
  field_and_operator = "#{parsed_field} #{parsed_operator}"
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "9.20.7"
2
+ VERSION = "9.20.8"
3
3
  end
@@ -45,6 +45,29 @@ module ForestLiana
45
45
  it { expect(parsed_filters.count).to eq 1 }
46
46
  end
47
47
 
48
+ context 'equal on a null value (JSON null from the UI)' do
49
+ before do
50
+ Tree.create!(name: nil, age: 42, island: Island.first)
51
+ Tree.create!(name: 'null', age: 43, island: Island.first)
52
+ end
53
+
54
+ let(:filters) { { 'field' => 'name', 'operator' => 'equal', 'value' => nil } }
55
+
56
+ it 'matches rows where the column IS NULL, not the literal string "null"' do
57
+ expect(parsed_filters.pluck(:name)).to eq([nil])
58
+ end
59
+ end
60
+
61
+ context 'not_equal on a null value (JSON null from the UI)' do
62
+ before { Tree.create!(name: nil, age: 42, island: Island.first) }
63
+
64
+ let(:filters) { { 'field' => 'name', 'operator' => 'not_equal', 'value' => nil } }
65
+
66
+ it 'matches rows where the column IS NOT NULL' do
67
+ expect(parsed_filters.pluck(:name)).to match_array(['Tree n1', 'Tree n2', 'Tree n3'])
68
+ end
69
+ end
70
+
48
71
  context 'greater_than' do
49
72
  let(:filters) { { 'field' => 'age', 'operator' => 'greater_than', 'value' => 2 } }
50
73
  it { expect(parsed_filters.count).to eq 2 }
@@ -107,6 +130,14 @@ module ForestLiana
107
130
  it { expect(parsed_filters.count).to eq 0 }
108
131
  end
109
132
 
133
+ context 'equal on an unknown enum value' do
134
+ # The enum mapping nils an unknown value; the null-filter guard is
135
+ # keyed on the pre-mapping value so it must NOT become `IS NULL`
136
+ # (that would wrongly match rows whose joined cutter is absent).
137
+ let(:filters) { { 'field' => 'cutter:title', 'operator' => 'equal', 'value' => 'not_a_title' } }
138
+ it { expect(parsed_filters.count).to eq 0 }
139
+ end
140
+
110
141
  context 'contains' do
111
142
  let(:filters) { { 'field' => 'owner:title', 'operator' => 'contains', 'value' => 'in' } }
112
143
  it { expect(parsed_filters.count).to eq 3 }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.20.7
4
+ version: 9.20.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-03 00:00:00.000000000 Z
11
+ date: 2026-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails