diff --git a/app/lib/teacher_training_courses/api_client.rb b/app/lib/teacher_training_courses/api_client.rb new file mode 100644 index 000000000..bcae7017a --- /dev/null +++ b/app/lib/teacher_training_courses/api_client.rb @@ -0,0 +1,40 @@ +require "net/http" + +module TeacherTrainingCourses + class ApiClient + BASE_URL = + "https://api.publish-teacher-training-courses.service.gov.uk/api/public/v1".freeze + + class << self + def get(endpoint) + request(method: :get, endpoint:) + end + + def get_all_pages(endpoint) + results = [] + is_last_page = false + + until is_last_page + response = request(method: :get, endpoint:) + results.concat response.fetch("data") + + if (next_page = response.dig("links", "next")) + endpoint = next_page.delete_prefix(BASE_URL) + else + is_last_page = true + end + end + + results + end + + private + + def request(method:, endpoint:) + url = URI("#{BASE_URL}#{endpoint}") + response = Net::HTTP.public_send(method, url) + JSON.parse(response) + end + end + end +end diff --git a/app/lib/teacher_training_courses/provider.rb b/app/lib/teacher_training_courses/provider.rb new file mode 100644 index 000000000..ce0085000 --- /dev/null +++ b/app/lib/teacher_training_courses/provider.rb @@ -0,0 +1,51 @@ +module TeacherTrainingCourses + class Provider + ATTRIBUTES = %i[code name email website ukprn accredited_body].freeze + + attr_reader(*ATTRIBUTES) + + def initialize(_code, attributes) + ATTRIBUTES.each do |attribute| + attribute = attribute.to_s + instance_variable_set("@#{attribute}", attributes[attribute]) + end + end + + class << self + def all + providers_from_api.map { |code, attributes| new(code, attributes) } + end + + def find(code) + if (attributes = providers_from_api[code]) + new(code, attributes) + else + raise ProviderNotFound, code + end + end + + private + + def providers_from_api + @providers_from_api ||= Rails.cache.fetch("providers_from_api", expires_in: 1.hour) do + # Fetch all providers from the Teacher Training Courses API + providers = ApiClient.get_all_pages("/recruitment_cycles/2024/providers") + + # Drop attributes we don't need + providers = providers.map do |provider| + provider["attributes"].select { |key, _value| ATTRIBUTES.include?(key.to_sym) } + end + + # Transform to a Hash indexed by provider code + providers.index_by { |provider| provider["code"] } + end + end + end + + class ProviderNotFound < StandardError + def initialize(code) + super("Couldn't find provider with code '#{code}'") + end + end + end +end diff --git a/spec/lib/teacher_training_courses/api_client_spec.rb b/spec/lib/teacher_training_courses/api_client_spec.rb new file mode 100644 index 000000000..047beb2eb --- /dev/null +++ b/spec/lib/teacher_training_courses/api_client_spec.rb @@ -0,0 +1,11 @@ +require "rails_helper" + +RSpec.describe TeacherTrainingCourses::ApiClient do + describe ".get" do + it "makes a GET request to the API" do + stub_providers + debugger + expect(described_class.get("/recruitment_cycles/2024/providers")).to eq("Hello") + end + end +end diff --git a/spec/lib/teacher_training_courses/provider_spec.rb b/spec/lib/teacher_training_courses/provider_spec.rb new file mode 100644 index 000000000..24c16446d --- /dev/null +++ b/spec/lib/teacher_training_courses/provider_spec.rb @@ -0,0 +1,24 @@ +require "rails_helper" + +RSpec.describe TeacherTrainingCourses::Provider do + describe ".all" do + it "makes a GET request to the API" do + stub_providers + expect(described_class.all).to eq [] + end + end + + describe ".find" do + it "gets a specific provider by its code" do + stub_providers([ + build(:teacher_training_courses_provider, code: "T92", name: "Example provider") + ]) + + provider = described_class.find("T92") + + expect(provider).to be_a TeacherTrainingCourses::Provider + expect(provider.code).to eq "T92" + expect(provider.name).to eq "Example provider" + end + end +end