maestrano/maestrano-connector-rails

View on GitHub
app/resources/maestrano/api/base_resource.rb

Summary

Maintainability
A
45 mins
Test Coverage
module Maestrano
  module Api
    class BaseResource < JSONAPI::Resource
      abstract
      include Pundit::Resource

      API_SQL_OPERATOR_MAPPING = {
        gt: '>',
        gte: '>=',
        lt: '<',
        lte: '<=',
        ne: '<>',
        like: 'LIKE'
      }.freeze

      def self.all_filters
        # Skipping if there is no tables as calling columns_hash in attribute_type is causing issue
        return unless tables_exists?

        _attributes.keys.each do |attribute|
          type = attribute_type(attribute)
          if type == :boolean
            # https://github.com/cerebris/jsonapi-resources/issues/852
            # make sure filter applied on boolean works
            filter(attribute, verify: :verify_boolean_filter)
          else
            filter(attribute)
          end
        end
        generate_composite_filters
      end

      def self.generate_composite_filters
        _allowed_filters.keys.each do |key|
          # iterating through all the api operator and adding them as custom filter
          # name.gt, name.like etc...
          next unless _model_class

          field = "#{_model_class.table_name}.#{key}"

          API_SQL_OPERATOR_MAPPING.each do |api_operator, sql_operator|
            filter "#{key}.#{api_operator}",
                   apply: ->(records, value, _options) { records.where("#{field} #{sql_operator} ?", value[0]) }
          end
          filter "#{key}.none",
                 apply: ->(records, value, _options) { records.where("#{field} IS NULL") }
          filter "#{key}.not",
                 apply: ->(records, value, _options) { value[0] ? records.where("#{field} <> ?", value[0]) : records.where("#{field} IS NOT NULL") }
          filter "#{key}.nin",
                 apply: ->(records, value, _options) { records.where("#{field} NOT IN (?)", value) }
          filter "#{key}.in",
                 apply: ->(records, value, _options) { records.where("#{field} IN (?)", value) }
        end
      end

      def self.attribute_type(attribute)
        _model_class.columns_hash[attribute.to_s]&.type || :string
      rescue
        :string
      end

      # If the code is loaded before table are created (during a schema:load for example) this will return false
      def self.tables_exists?
        @tables_exists = ActiveRecord::Base.connection.table_exists?('users') if @tables_exists.nil?
        @tables_exists
      end
    end
  end
end