Getting Started With Authoritex View Source

About

An Elixir library for searching and fetching controlled vocabulary authority terms, inspired by the Samvera Community's Questioning Authority.

Authoritex provides an Elixir behaviour that defines a specification for creating authorities. Each authority is a module which has to implement at least 5 public functions: can_resolve?/1, code/0, description/0, fetch/1, and search/2.

  • can_resolve?/1 Returns true if the module can resolve the given identifier
  • code/0 Returns the unique short code for the authority
  • description/0 Returns a human-readable description of the authority
  • fetch/1 Fetches a label (and optional hint string) for a specified resource
  • search/2 Returns a list of search results (and optional hints) matching a query

Installation

Mix.install([
  {:authoritex, "~> 0.7.0"}
])

Configuration

Application.put_env(:authoritex, :authorities, [
  Authoritex.FAST.CorporateName,
  Authoritex.FAST.EventName,
  Authoritex.FAST.Form,
  Authoritex.FAST.Geographic,
  Authoritex.FAST.Personal,
  Authoritex.FAST.Topical,
  Authoritex.FAST.UniformTitle,
  Authoritex.FAST,
  Authoritex.GeoNames,
  Authoritex.Getty.AAT,
  Authoritex.Getty.TGN,
  Authoritex.Getty.ULAN,
  Authoritex.Getty,
  Authoritex.LOC.Languages,
  Authoritex.LOC.Names,
  Authoritex.LOC.SubjectHeadings
])

List configured authorities

Authoritex.authorities/0 returns a list of tuples describing all configured authorities.

Authoritex.authorities()

Fetch records by id

Authoritex.fetch/1 returns a map with the :label, :id, :hint, and :qualified_label for an authority record given an id (must be a string).

# Known authority and record identifier
Authoritex.fetch("http://id.loc.gov/authorities/names/no2011087251")

Authoritex.fetch/1 returns the error tuple {:error, 404} given an unknown id for a properly configured authority.

# Known authority with unknown record identifier
Authoritex.fetch("http://id.loc.gov/authorities/names/unknown-id")

Authoritex.fetch/1 returns the error tuple {:error, :unknown_authority} given an id for an unknown authority.

# Unknown authority
Authoritex.fetch("http://fake.authority.org/not-a-real-thing")

Search an authority

Authoritex.search/2 takes an authority code and search term (both arguments must be strings), and responds with either an :ok or an :error tuple. Search results are returned as a list of maps containing the :id, :label and :hint values for each result.

Enter a search term in the field below and choose an authority to search from the select dropdown. Selecting a different authority will automatically re-run the search below:

Authoritex.search(IO.gets("select authority: ") |> String.trim(), IO.gets("search term: "))

Authoritex.search/3 takes the same arguments as Authoritex.search/2 along with a third argument (must be an integer) to limit the result count of the search.

Authoritex.search("lcsh", "library", 3)
# Error recevied when searching an unknown authority
Authoritex.search("not-an-authority", "test")

Testing

Authoritex provides a mock for testing purposes in consuming applications.

Configure the mock with a few lines of code:

# In test.exs:
config :authoritex, authorities: [Authoritex.Mock]

# In test_helper.exs:
Authoritex.Mock.init()

Use the Authoritex.Mock.set_data/1 function to add data for testing purposes, typically in a setup block. The example module below demonstrates an ExUnit test using the Authoritex.Mock. The Authoritex.Mock.search/1 function returns all mock data regardless of the string passed to the function. (Note: the following code is a code sample that is not runnable like the examples above):

defmodule MyTest do
  alias Authoritex.Mock
  use ExUnit.Case, async: true

  @data [
      %{
        id: "mock:result1",
        label: "First Result",
        qualified_label: "First Result (1)",
        hint: "(1)"
      },
      %{
        id: "mock:result2",
        label: "Second Result",
        qualified_label: "Second Result (2)",
        hint: "(2)"
      },
      %{id: "mock:result3", label: "Third Result", qualified_label: "Third Result (3)", hint: "(3)"}
    ]

  setup do
    Mock.set_data(@data)
    :ok
  end

  test "results" do
    with {:ok, results} <- Mock.search("any") do
      assert length(results) == length(@data)
    end
  end
end