sanger/sequencescape

View on GitHub
app/api/endpoints/searches.rb

Summary

Maintainability
A
35 mins
Test Coverage
A
100%
# frozen_string_literal: true
# Controls API V1 {::Core::Endpoint::Base endpoints} for Searches
class Endpoints::Searches < Core::Endpoint::Base
  module SearchActions
    def search_action(name) # rubocop:todo Metrics/AbcSize
      bind_action(:create, to: name.to_s, as: name.to_sym) do |action, request, response|
        request.json['search']['page'] ||= request.path.fetch(1).to_i if request.path.fetch(1, false)
        scope = request.target.scope(request.json['search']).send(name)

        # If we're not paginated, just convert to an array. This will stop
        # the api from trying to paginate the results. Ideally all searches should be
        # paginated, but this may break downstream clients
        (scope.respond_to?(:total_entries) ? scope : scope.to_a).tap do |results|
          response.handled_by = action
          yield(response, results)
        end
      end
    end

    def singular_search_action(name) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
      bind_action(:create, to: name.to_s, as: name.to_sym) do |_action, request, response|
        record = request.target.scope(request.json['search']).send(name.to_sym)
        raise ActiveRecord::RecordNotFound, 'no resources found with that search criteria' if record.nil?

        request.io = ::Core::Io::Registry.instance.lookup_for_object(record)
        request
          .io
          .eager_loading_for(record.class)
          .include_uuid
          .find(record.id)
          .tap { |_result| response.redirect_to(record.uuid) }
      end
    end
  end

  model {}

  instance do
    extend SearchActions

    singular_search_action(:first)
    singular_search_action(:last)

    search_action(:all) { |response, _records| response.multiple_choices }
  end
end