Jbuilder
Constants
Constructors
Class methods
Instance methods
Коллекция с атрибутами: array! people, :name, :age / json.comments comments, :content.
Ключ: String или Symbol → String (runtime, т.к. через method_missing аргументы приходят как значения).
Без рестрикшена Array(Node): рекурсивный alias в ограничении аргумента не матчит фактический Array(Node) при вызове из тела метода, унаследо- ванного подклассом (json.array! в JbuilderTemplate уводило вызов в method_missing с ключом "_set_array") — см. баги Crystal 1.21 ниже.
array! — те же ветви, что в Ruby: array! [1,2,3] / array!(nil) / array! coll { |el| ... } / array! coll, :name
json.(obj, :name) / json.(coll) { |el| ... } — call-синтаксис (здесь json.call).
extract! obj, :name, :age — Hash / NamedTuple / JSON::Any / ivar-методы объекта.
key_format! :upcase / key_format! camelize: :lower / key_format! ->(k){ "_"+k } (splat без аннотации: annotated-splat + named-args ломают диспетчеризацию Crystal и приводят к method_missing)
set! — макрос: ветвится по наличию блока/атрибутов, как set! в Ruby. json.name "David" → {"name":"David"} json.author { json.name "David" } → {"author":{...}} json.person other_builder → {"person":{...}} json.people people { |p| ... } → {"people":[...]} json.author david, :name, :age → {"author":{...}} json.comments comments, :content → {"comments":[...]} set! — def-методы (yield-based), те же ветви, что в Ruby: json.name "David" → {"name":"David"} json.author { json.name "David" } → {"author":{...}} json.person other_builder → {"person":{...}} json.people people { |p| ... } → {"people":[...]} json.author david, :name, :age → {"author":{...}} json.comments comments, :content → {"comments":[...]} При блоке атрибуты игнорируются (семантика Ruby: block_given? первым).
nil-коллекция с блоком → [] (Ruby: array! nil → [])
Macros
method_missing → set! (json.name "David" — 1:1 к Ruby, где method_missing = set!). DSL-методы (set!/array!/extract!/call) — обычные def-методы и находятся напрямую, сюда попадают только произвольные имена ключей. Аргументы приходят переименованными (_arg0) и обрабатываются на этапе выполнения.