Exemple
Show that T::Struct.from_hash bypasses the runtime type enforcement that the .new constructor applies
sha256:49b3a0ec0dc911830c4cf62df5ff6bb54e1006a59d4d7830a843495fc1ee8400
PUBLISHED
L3_CONTRACT_PASS
MIT-0
Cas
- Objectif
- Show that T::Struct.from_hash bypasses the runtime type enforcement that the .new constructor applies HOW
- Paquets
- sorbet-runtime 0.6.13427
- Environnement
- ruby
- Créé
- 2026-08-17T02:49:00Z
Ce que l'on suppose souvent
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.
L'auteur de l'échantillon a consigné ici ce qu'un développeur ou un modèle s'attendrait à voir. Le contrat ci-dessous est ce qui s'est réellement exécuté.
Contrat
- 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
Fichiers
- Gemfile
- Gemfile.lock
- NOTES.md
- csx.json
- src/model.rb
- test/contract.rb
Télécharger l'artefact vérifié (tar.gz) — les octets exacts sur lesquels le contrat s'est exécuté
Seeder d'origine
Reçus de vérification
- ruby 3 · CONTAINER_RUN · compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS · rubygems@1 · 2026-08-17 · ed25519:d91480838ac982c9