jsonapi-suite / jsonapi_compliable

MIT License
20 stars 35 forks source link

Add advanced filtering #119

Closed richmolj closed 6 years ago

richmolj commented 6 years ago

Attributes have types, and types have default filters. For example:

 # strings
?filter[name][eq]=foo # case insensitive
?filter[name][eql]=foo # case sensitive
?filter[name][prefix]=fo
?filter[name][suffix]=fo
?filter[name][like]=o
?filter[name]=foo # default is eq

 # add a bang for "not"
?filter[name][!eq]=foo
?filter[name][!like]=o

 # integers, datetimes, etc
?filter[age][eq]=10
?filter[age][gt]=10
?filter[age][gte]=10
?filter[age][lt]=10
?filter[age][lte]=10

To customize the logic:

 # in your resource
attribute :name, :string

filter :name do
  eq do
    # custom eq logic
  end
end

 # if a corresponding attribute does not exist
filter :foo, :string do
  eq do
    # logic
  end
end

 # you can also add arbitrary operators
filter :foo, :string do
  bar do
    # logic
  end
end

Add global operators for types by adding the corresponding method name to your adapter:

def filter_integer_foo(scope, attribute, value)
  # logic
end

 # gives you this, assuming foo is an integer
?filter[age][foo]=111

We also now accept dot-notation for relationship filtering. The "official" syntax will be type-based (?filter[people][id]=1) or relationship dot-based (?filter[authors.id]=1). Relationship-based (?filter[authors][id]=1) will be supported but deprecated.

Dot-based filtering can go multiple levels, ie ?filter[positions.department.name]=foo.

Other notes:

richmolj commented 6 years ago

@wadetandy

richmolj commented 6 years ago

I think we also need to support not_

Not tested but I believe supported (we actually transform ! to _not under the hood). Will add a test when I circle back around.