Jsonapi-resources: Validate filter value

Created on 23 Aug 2017  路  4Comments  路  Source: cerebris/jsonapi-resources

Hi all, Congrats for the project!
Is there a way to validate filter values?
For example, I want to filter by name, but only if the name value is a string with more than 3 characters.
Is there a standard way to do this?
I couldn't find any documentation about this.

Most helpful comment

@edipox, JR does not support filters validators, but you can implement it yourself by overriding verify_filter.
something like code below can do the trick:

class JSONAPI::Validators::LengthValidator
  def initialize(filter_name, values, options)
    @filter_name = filter_name
    @values = values
    @options = options
  end

  def valid?
    return false if !options[:allow_empty] && values.empty?
    values.each do |value|
      return false if options[:min] && value.length < options[:min]
      return false if options[:max] && value.length > options[:max]
    end
    true
  end
end

class ApplicationResource < JSONAPI::Resource
  def self.verify_filter(filter, raw, context = nil)
    result = super
    options = _allowed_filters.fetch(filter, {})
    options.fetch(:validate, {}).each do |validator, opts|
      klass = "JSONAPI::Validators::#{validator.to_s.classify}Validator".constantize
      unless klass.new(result[0], result[1], opts).valild?
        raise JSONAPI::Exceptions::InvalidFilterValue.new(filter, raw)
      end
    end
    result
  end
end

class UserResource < ApplicationResource
  attribute :name
  filter :name, validate: { length: { min: 3, max: 20 } }
end

All 4 comments

I haven't tried, but I assume you could just raise an error inside the filter callback. See http://jsonapi-resources.com/v0.9/guide/resources.html#Applying-Filters for how to implement a custom filter.

Thank you @scottgonzalez ! I have already looked at that doc.
What I was doing is something like:

      filter :name, verify: ->(values, context) {
        raise JSONAPI::Exceptions::InvalidFilterValue.new(:name, values) if ...
      }

But I'm wondering if there is a standard way to validate the filter values, and return an error with all the "wrong" filters, something like:

{
    "errors": [
        {
            "title": "Invalid filter value",
            "detail": "[\"10\"] is not a valid value for name.",
            "code": "107",
            "status": "400"
        },
        {
            "title": "Invalid filter value",
            "detail": "[\"10\"] is not a valid value for last_name.",
            "code": "107",
            "status": "400"
        }
    ]
}

BTW: It would be nice if we could something like:

filter :name, validate: { lenght: { min: 3, max: 20 } }

@edipox, JR does not support filters validators, but you can implement it yourself by overriding verify_filter.
something like code below can do the trick:

class JSONAPI::Validators::LengthValidator
  def initialize(filter_name, values, options)
    @filter_name = filter_name
    @values = values
    @options = options
  end

  def valid?
    return false if !options[:allow_empty] && values.empty?
    values.each do |value|
      return false if options[:min] && value.length < options[:min]
      return false if options[:max] && value.length > options[:max]
    end
    true
  end
end

class ApplicationResource < JSONAPI::Resource
  def self.verify_filter(filter, raw, context = nil)
    result = super
    options = _allowed_filters.fetch(filter, {})
    options.fetch(:validate, {}).each do |validator, opts|
      klass = "JSONAPI::Validators::#{validator.to_s.classify}Validator".constantize
      unless klass.new(result[0], result[1], opts).valild?
        raise JSONAPI::Exceptions::InvalidFilterValue.new(filter, raw)
      end
    end
    result
  end
end

class UserResource < ApplicationResource
  attribute :name
  filter :name, validate: { length: { min: 3, max: 20 } }
end

Thank you @senid231! That looks good. I'm just using verify for now. So I'll close this issue

Was this page helpful?
0 / 5 - 0 ratings