Пример
Show that T::Struct.from_hash bypasses the runtime type enforcement that the .new constructor applies
sha256:49b3a0ec0dc911830c4cf62df5ff6bb54e1006a59d4d7830a843495fc1ee8400
PUBLISHED
L3_CONTRACT_PASS
MIT-0
Кейс
- Цель
- Show that T::Struct.from_hash bypasses the runtime type enforcement that the .new constructor applies HOW
- Пакеты
- sorbet-runtime 0.6.13427
- Окружение
- ruby
- Создан
- 2026-08-17T02:49:00Z
Что обычно предполагают
Because T::Struct declares prop types and the .new constructor raises TypeError when a value does not match, from_hash — the documented deserialization path — applies the same check and raises on mismatched types.
Автор образца записал здесь то, чего ожидал бы разработчик или модель. Контракт ниже — это то, что действительно выполнялось.
Контракт
- T::Struct.from_hash accepts a String value for a prop declared Integer and returns it unchanged without raising TypeError, while T::Struct.new raises TypeError for the identical input — proving that the deserialization path skips the sig-based check the constructor applies
- assert ConnectionRecord.from_hash('port' => '5432').port == '5432'
- assert ConnectionRecord.new(port: '5432') raises TypeError matching /Can't set ConnectionRecord\.port/
- assert from_hash with an unknown string key silently discards it rather than raising
- assert from_hash with symbol keys treats them as absent and raises RuntimeError about nil deserialization
- assert from_hash with Integer elements inside a T::Array[String] prop returns them unchanged — element types are not checked
Файлы
- Gemfile
- Gemfile.lock
- NOTES.md
- csx.json
- src/model.rb
- test/contract.rb
Скачать проверенный артефакт (tar.gz) — те самые байты, на которых выполнялся контракт
Исходный сидер
Квитанции проверки
- ruby 3 · CONTAINER_RUN · compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS · rubygems@1 · 2026-08-17 · ed25519:d91480838ac982c9