From d0d515a948be60be0c1edff82573378bb421a567 Mon Sep 17 00:00:00 2001 From: Brooke Kuhlmann Date: Tue, 13 Jan 2026 09:58:42 -0700 Subject: [PATCH] Added recipe model Necessary to model the data from the Recipes API. This leverages the `Entry` model which encapsulates the `data` attribute while the other keys are pagination related. Milestone: minor --- lib/trmnl/api/container.rb | 1 + lib/trmnl/api/models/recipe.rb | 24 ++++++ spec/lib/trmnl/api/models/recipe_spec.rb | 95 ++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 lib/trmnl/api/models/recipe.rb create mode 100644 spec/lib/trmnl/api/models/recipe_spec.rb diff --git a/lib/trmnl/api/container.rb b/lib/trmnl/api/container.rb index 44aad0d..e64ea8c 100644 --- a/lib/trmnl/api/container.rb +++ b/lib/trmnl/api/container.rb @@ -38,6 +38,7 @@ module TRMNL register :ip_address, Models::IPAddress register :model, Models::Model register :palette, Models::Palette + register :recipe, Models::Recipe register :setup, Models::Setup end end diff --git a/lib/trmnl/api/models/recipe.rb b/lib/trmnl/api/models/recipe.rb new file mode 100644 index 0000000..3ecf4bf --- /dev/null +++ b/lib/trmnl/api/models/recipe.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module TRMNL + module API + module Models + # Models the data of the API response. + Recipe = Data.define( + :data, + :total, + :from, + :to, + :per_page, + :current_page, + :prev_page_url, + :next_page_url + ) do + def self.for(**attributes) + data = attributes[:data].map { Recipes::Entry.for(**it) } + new(**attributes.merge!(data:)) + end + end + end + end +end diff --git a/spec/lib/trmnl/api/models/recipe_spec.rb b/spec/lib/trmnl/api/models/recipe_spec.rb new file mode 100644 index 0000000..5c257bd --- /dev/null +++ b/spec/lib/trmnl/api/models/recipe_spec.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe TRMNL::API::Models::Recipe do + describe ".for" do + let :attributes do + { + data: [ + { + id: 1, + name: "Test", + published_at: "2026-01-13T13:00:32.349Z", + icon_url: "https://icons.trmnl.io/test.png", + icon_content_type: "image/png", + screenshot_url: "https://screens.trmnl.io/test.png", + author_bio: { + keyname: "test", + name: "Test", + field_type: "author_bio", + description: "A test.", + github_url: "https://github.com/test/test", + learn_more_url: "https://test.info" + }, + custom_fields: [ + { + keyname: "test", + name: "Test", + field_type: "A test bio.", + description: "Displays test data.", + github_url: "https://github.com/test/test", + learn_more_url: "https://test.info" + } + ], + stats: { + installs: 6, + forks: 0 + } + } + ], + total: 100, + from: 1, + to: 25, + per_page: 25, + current_page: 1, + prev_page_url: nil, + next_page_url: "/recipes.json?page=2" + } + end + + it "answers record for attributes" do + expect(described_class.for(**attributes)).to eq( + described_class[ + data: [ + TRMNL::API::Models::Recipes::Entry[ + id: 1, + name: "Test", + published_at: "2026-01-13T13:00:32.349Z", + icon_url: "https://icons.trmnl.io/test.png", + icon_content_type: "image/png", + screenshot_url: "https://screens.trmnl.io/test.png", + author: TRMNL::API::Models::Recipes::Author[ + keyname: "test", + name: "Test", + field_type: "author_bio", + description: "A test.", + description_locales: {}, + github_url: "https://github.com/test/test", + learn_more_url: "https://test.info" + ], + custom_fields: [ + { + keyname: "test", + name: "Test", + field_type: "A test bio.", + description: "Displays test data.", + github_url: "https://github.com/test/test", + learn_more_url: "https://test.info" + } + ], + statistics: TRMNL::API::Models::Recipes::Statistics[installs: 6, forks: 0] + ] + ], + total: 100, + from: 1, + to: 25, + per_page: 25, + current_page: 1, + prev_page_url: nil, + next_page_url: "/recipes.json?page=2" + ] + ) + end + end +end