From 252a28ef309796033817202f7ab7f731ea945ade Mon Sep 17 00:00:00 2001 From: Brooke Kuhlmann Date: Fri, 18 Jul 2025 13:09:40 -0600 Subject: [PATCH] Added model Necessary to provide a whole value object as the output from the API response. Milestone: minor --- lib/trmnl/api/models/model.rb | 67 +++++++++++++++++++++ spec/lib/trmnl/api/models/model_spec.rb | 77 +++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 lib/trmnl/api/models/model.rb create mode 100644 spec/lib/trmnl/api/models/model_spec.rb diff --git a/lib/trmnl/api/models/model.rb b/lib/trmnl/api/models/model.rb new file mode 100644 index 0000000..10c397a --- /dev/null +++ b/lib/trmnl/api/models/model.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module TRMNL + module API + module Models + # Models data for API display responses. + Model = Struct.new( + :name, + :label, + :description, + :colors, + :bit_depth, + :scale_factor, + :rotation, + :mime_type, + :width, + :height, + :offset_x, + :offset_y, + :published_at + ) do + def self.for(attributes) = new(**attributes) + + def initialize(**) + super + apply_defaults + freeze + end + + def to_json(*) = to_h.to_json(*) + + private + + def apply_defaults + %i[colors bit_depth scale_factor rotation width height offset_x offset_y].each do |name| + self[name] ||= 0 + end + end + end + end + end +end + +# TODO: Remove when finished. +__END__ + +# frozen_string_literal: true + +module Kagi + module API + module Models + # Models the search payload. + Search = Data.define :meta, :data do + def self.for(**attributes) + new( + **attributes.merge!( + meta: Content::Meta.for(**attributes[:meta]), + data: attributes[:data].map { Content::Search.for(**it) } + ) + ) + end + end + end + end +end + + diff --git a/spec/lib/trmnl/api/models/model_spec.rb b/spec/lib/trmnl/api/models/model_spec.rb new file mode 100644 index 0000000..eb75489 --- /dev/null +++ b/spec/lib/trmnl/api/models/model_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe TRMNL::API::Models::Model do + subject(:model) { described_class.new } + + describe ".for" do + let :attributes do + { + name: "test", + label: "Test", + description: "A test.", + colors: 2, + bit_depth: 1, + scale_factor: 1, + rotation: 90, + mime_type: "image/png", + width: 800, + height: 480, + offset_x: 10, + offset_y: 15, + published_at: "2025-07-16T18:18:11+00:00" + } + end + + it "answers record for attributes" do + expect(described_class.for(attributes)).to eq(described_class[**attributes]) + end + end + + describe "#initialize" do + it "answers default attributes" do + expect(model.to_h).to eq( + name: nil, + label: nil, + description: nil, + colors: 0, + bit_depth: 0, + scale_factor: 0, + rotation: 0, + mime_type: nil, + width: 0, + height: 0, + offset_x: 0, + offset_y: 0, + published_at: nil + ) + end + + it "is frozen" do + expect(model.frozen?).to be(true) + end + end + + describe "#to_json" do + it "answers JSON" do + payload = JSON model.to_json, symbolize_names: true + + expect(payload).to eq( + name: nil, + label: nil, + description: nil, + colors: 0, + bit_depth: 0, + scale_factor: 0, + rotation: 0, + mime_type: nil, + width: 0, + height: 0, + offset_x: 0, + offset_y: 0, + published_at: nil + ) + end + end +end