-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How can we use custom filters? #73
Comments
Hi there, @daniffig. Sorry for the long late on answering you. I'm having some pretty busy days here, but I'll try to be quicker. Yes, As you mentioned, Let me show a quick usage example: # app/resources/user_resource.rb
class UserResource < JSONAPI::Resource
attributes :first_name, :last_name
custom_filter :name
end
# app/controllers/users_controller.rb
class UsersController < BaseController
# GET /users
def index
searcher = UserSearcher.new(collection: User.all, name: params.dig(:filter, :name)
jsonapi_render json: searcher.call
end
end I may be adding some specs + documentation around this feature soon. I hope this helped you. |
I'm using it as you explained and it works great. However, IMO it would be better if we hooked the custom filters to the filter chain, so they can be resolved by the resource, just as JR proposes. So we could code something like this. # app/resources/user_resource.rb
class UserResource < JSON::Resource
attributes :first_name, :last_name
custom_filter :name
def self.name(records, value, _options)
records.where("users.first_name LIKE ?", "%#{value}%")
end
end |
For now JU doesn't push a design pattern for achieving such a feature, thus letting devs to put their logic where they think it's better (i.e. service object, interactor or even controllers). The initial idea of using the resource layer from JR was to take advantage of its internal DSL only for describing the resource's properties like its attributes, relationships, filters and for some serialization-related stuff. Thus the operations (like that sample custom filter) should rather go to a layer where it makes more sense for an usual Rails application. Anyway, I may consider what you've suggested and bring this feature as something optional. And by this I mean: if the Thanks for the feedback. |
I think that's a great proposal. I've developed a custom server plugin for Symfony 1.4 in the past using JSON API v0.9 definitions, and when the API usage grows the need of complex filters does it too. Clauses like >, <, LIKE, BETWEEN are a must-have, you just can't avoid them if your resource represents large collections. Since JSON API allows to use the reserved word 'filter' as you please, we implemented a filter object with 'field', 'value', 'method' as its params. A preprocessor then converted it to an ActiveRecord query. I think JR approach is cleaner than the one we used, however filters like :name_contains, :created_since, or :updated_between are common word and should have a simple solution. Thank you for such a great gem! |
I needed to filter by multiple values. i added a the following before filter in my controller. The values are pipe separated or comma separated in that order, so if my filter values might have commas in them, i user pipe instead. before_action :process_filters, only: [:index]
def process_filters
if params[:filter].present?
params[:filter].each do |k, v|
values = v.try(:split, '|')
values = v.try(:split, ',') if values.size <= 1
params[:filter][k] = values
end
end
end |
But JR supports custom filters on the resource level, using apply/verify. Current behavior of this gem is doubtful, as it supports "some" filters from JR, but not all of them. And it forces to implement filters in other place, spreading such logic across the project. I wish I'd noticed it before :/ |
I'm having some trouble while filtering. I need my resource to be filtered by its name using a LIKE query (autocomplete field). If I implement JSONAPI::Resources approach, using a lambda, it doesn't work, the lambda it's not called. JSONAPI::Utils provides a custom_filters method, which allows me to apply the filter in the controller, but I don't think that is the best solution. Am I missing something? I can't find any further documentation. Could it be possible to implement all custom filtering code in the resource instead of the controller, as JR proposes?
The text was updated successfully, but these errors were encountered: