datacite/lupo

View on GitHub
app/models/provider_prefix.rb

Summary

Maintainability
A
2 hrs
Test Coverage
F
57%
# frozen_string_literal: true

class ProviderPrefix < ApplicationRecord
  # include helper module for caching infrequently changing resources
  include Cacheable

  # include helper module for Elasticsearch
  include Indexable

  include Elasticsearch::Model

  belongs_to :provider, touch: true
  belongs_to :prefix, touch: true
  has_many :client_prefixes, dependent: :destroy
  has_many :clients, through: :client_prefixes

  before_create :set_uid

  validates_presence_of :provider, :prefix

  # use different index for testing
  if Rails.env.test?
    index_name "provider-prefixes-test#{ENV['TEST_ENV_NUMBER']}"
  elsif ENV["ES_PREFIX"].present?
    index_name "provider-prefixes-#{ENV['ES_PREFIX']}"
  else
    index_name "provider-prefixes"
  end

  mapping dynamic: "false" do
    indexes :id, type: :keyword
    indexes :uid, type: :keyword
    indexes :state, type: :keyword
    indexes :provider_id, type: :keyword
    indexes :provider_id_and_name, type: :keyword
    indexes :consortium_id, type: :keyword
    indexes :prefix_id, type: :keyword
    indexes :client_ids, type: :keyword
    indexes :client_prefix_ids, type: :keyword
    indexes :created_at, type: :date
    indexes :updated_at, type: :date

    # index associations
    indexes :provider, type: :object
    indexes :prefix,
            type: :object,
            properties: {
              id: { type: :keyword },
              uid: { type: :keyword },
              provider_ids: { type: :keyword },
              client_ids: { type: :keyword },
              state: { type: :keyword },
              prefix: { type: :text },
              created_at: { type: :date },
            }
    indexes :clients, type: :object
    indexes :client_prefixes, type: :object
  end

  def as_indexed_json(options = {})
    {
      "id" => uid,
      "uid" => uid,
      "provider_id" => provider_id,
      "provider_id_and_name" => provider_id_and_name,
      "consortium_id" => consortium_id,
      "prefix_id" => prefix_id,
      "client_ids" => client_ids,
      "client_prefix_ids" => client_prefix_ids,
      "state" => state,
      "created_at" => created_at,
      "updated_at" => updated_at,
      "provider" => provider.try(:as_indexed_json, exclude_associations: true),
      "prefix" =>
        if options[:exclude_associations]
          nil
        else
          prefix.try(:as_indexed_json, exclude_associations: true)
        end,
      "clients" =>
        if options[:exclude_associations]
          nil
        else
          clients.map do |m|
            m.try(:as_indexed_json, exclude_associations: true)
          end
        end,
      "client_prefixes" =>
        if options[:exclude_associations]
          nil
        else
          client_prefixes.map do |m|
            m.try(:as_indexed_json, exclude_associations: true)
          end
        end,
    }
  end

  def self.query_aggregations
    {
      states: { terms: { field: "state", size: 2, min_doc_count: 1 } },
      years: {
        date_histogram: {
          field: "created_at",
          interval: "year",
          format: "year",
          order: { _key: "desc" },
          min_doc_count: 1,
        },
        aggs: { bucket_truncate: { bucket_sort: { size: 10 } } },
      },
      providers: {
        terms: { field: "provider_id_and_name", size: 10, min_doc_count: 1 },
      },
    }
  end

  def consortium_id
    provider.consortium_id.downcase if provider.consortium_id.present?
  end

  # convert external id / internal id
  def provider_id
    provider.symbol.downcase
  end

  def provider_id_and_name
    "#{provider_id}:#{provider.name}" if provider.present?
  end

  # convert external id / internal id
  def provider_id=(value)
    r = Provider.where(symbol: value).first
    fail ActiveRecord::RecordNotFound if r.blank?

    write_attribute(:provider_id, r.id)
  end

  # convert external id / internal id
  def prefix_id
    prefix.uid
  end

  # convert external id / internal id
  def prefix_id=(value)
    r = cached_prefix_response(value)
    fail ActiveRecord::RecordNotFound if r.blank?

    write_attribute(:prefix_id, r.id)
  end

  def client_ids
    clients.pluck(:symbol).map(&:downcase)
  end

  def client_prefix_ids
    client_prefixes.pluck(:uid)
  end

  def state
    client_prefix_ids.present? ? "with-repository" : "without-repository"
  end

  private
    # uuid for public id
    def set_uid
      self.uid = SecureRandom.uuid
    end
end