tsuwatch/nazrin

View on GitHub
lib/nazrin/data_accessor.rb

Summary

Maintainability
A
25 mins
Test Coverage
require 'nazrin/result'

module Nazrin
  class DataAccessor
    class NoAccessorError < StandardError; end

    class << self
      def for(clazz)
        accessor = registered_accessor_for(clazz) || register_accessor(clazz)
        return accessor if accessor
        raise NoAccessorError, "No accessor for #{clazz.name}"
      end

      def registered_accessor_for(clazz)
        return nil if clazz.name.nil? || clazz.name.empty?
        accessors[clazz.name.to_sym]
      end

      def register_accessor(clazz)
        clazz.ancestors.each do |ancestor_class|
          if accessor = accessor_for(ancestor_class)
            register(accessor, clazz)
            return accessor
          end
        end
        nil
      end

      def accessor_for(clazz)
        return nil if clazz.name.nil? || clazz.name.empty?

        if clazz.respond_to?(:nazrin_searchable_config) && clazz.nazrin_searchable_config.domain_name
          require 'nazrin/data_accessor/struct'
          return Nazrin::DataAccessor::Struct[clazz.nazrin_searchable_config]
        elsif defined?(::ActiveRecord::Base) && clazz.ancestors.include?(::ActiveRecord::Base)
          require 'nazrin/data_accessor/active_record'
          return Nazrin::DataAccessor::ActiveRecord
        elsif defined?(::Mongoid::Document) && clazz.ancestors.include?(::Mongoid::Document)
          require 'nazrin/data_accessor/mongoid'
          return Nazrin::DataAccessor::Mongoid
        end
        nil
      end

      def register(accessor, clazz)
        accessors[clazz.name.to_sym] = accessor
      end

      def accessors
        @accessor ||= {}
      end
    end

    attr_reader :model
    attr_reader :options

    def initialize(model, options)
      @model = model
      @options = options
    end

    def results(client)
      res = client.search
      collection = load_all(data_from_response(res))
      start = client.parameters[:start]
      size = client.parameters[:size]

      if size && start
        total_count = res.data.hits.found

        records = Nazrin::PaginationGenerator.generate(
          collection,
          current_page: current_page(start, size),
          per_page: size,
          total_count: total_count,
          last_page: last_page(size, total_count))
      else
        records = collection
      end

      Result.new(
        records,
        res.facets
      )
    end

    def load_all
      raise NotImplementedError
    end

    def data_from_response
      raise NotImplementedError
    end

    private

    def last_page(size, total_count)
      (total_count / size.to_f).ceil
    end

    def current_page(start, size)
      (start / size.to_f).ceil + 1
    end
  end
end