Logical `or` for filters
I would like to have logical or between filters, for example find the users whose first or last name is "Jones". I currently use the following to simulate it:
filter :|, :hash do
eq do |scope, vals|
vals.reduce(scope) do |res, fil|
fil.reduce(res) do |scop, (k, v)|
filt = filters[k]
v.reduce(scop) do |cur, (op, val)|
(
filt[:operators][op]&.call(base_scope, val, context) ||
adapter.try(
"filter_#{filt[:type]}_#{op}", base_scope, k, [*val]
)
).or(cur)
end
end
end
end
end
So now I can have something like
http://localhost:3000/api/v1/employees?filter[first_name]=bob&filter[|][last_name]=sponge
But I am not sure that this works correctly (for example, with respect to restrictions on filtering), and it uses private functions. I couldn't find it in the docs, and it appears that the jsonapi spec does not specify it. Can this feature be added (if it doesn't exist)?
@mkamensky There's a few ways to go about this, and depending on what you want I think this can be approached in different ways. If you specifically want to be able to filter first_name == 'foo' OR last_name == 'foo', then I would recommend adding a custom filter for that:
filter :first_or_last_name, :string do
eq do |scope, values|
scope.where('first_name IN (?) OR last_name IN (?)', values, values)
end
end
If you want a more dynamic query builder which includes nested ORs and ANDs, that's something which might take a bit more thought.
@wadetandy thanks, I actually want the latter, what I wrote was just an example. What I wrote above seems to work so far (I just fixed a small issue there), but I did not test it comprehensively. Also, I don't know if there is a standard syntax for this.
@mkamensky we thought about this a bit before:

I'd really, really like to see something like this in Graphiti. I think it's a powerful, defining feature that shouldn't be TOO hard to implement if you wanted to take a stab at it.
@richmolj Thanks. This is what I was looking for, but I don't see myself implementing this in the near future, sorry... Perhaps in the meanwhile the hack above can be useful