ClsRuby позволяет не только разбирать входные потоки с Cls-тегами, но и формировать такие потоки. Для этого необходимо:
подготовить набор Cls-тегов, которые будут отображены в выходной поток. Каждый тег должен быть определенным, т.е. для него должен быть вызван метод ClsRuby::Tag::tag_make_defined (это очень важно, поскольку не определенные теги не форматируются);
создать объект-форматтера, реализующий интерфейс ClsRuby::TagFormatter;
передать форматер в метод ClsRuby::Tag::tag_format корневого тега, подлежащего форматированию.
ClsRuby предоставляет готовые реализации интерфейса ClsRuby::TagFormatter – классы ClsRuby::OneLineFormatter (располагающий весь Cls-поток в одну строку) и ClsRuby::DefaultFormatter (который использует отступы и переводы строк для упрощения чтения отформатированного Cls-потока).
Пусть требуется реализовать форматирование тега {project-description}:
{project-description {name <str> } {comment <str> } {source-files <str>* } }
для этого создается структура ProjectDescription, которая будет содержать описание проекта и класс тега TagProjectDescription:
require 'cls-ruby' require 'cls-ruby/tag_no_value' require 'cls-ruby/tag_scalar' require 'cls-ruby/tag_scalar_vector' require 'cls-ruby/default_formatter' ProjectDescription = Struct.new( :name, :comment, :source_files ) class TagProjectDescription < ClsRuby::TagNoValue mandatory_child_tag :name, ClsRuby::TagStringScalar mandatory_child_tag :comment, ClsRuby::TagStringScalar mandatory_child_tag :source_files, ClsRuby::TagScalarVector, :format => ClsRuby::SCALAR_STRING, :name => 'source-files' default_tag_params :name => 'project-description' # Конструктор проверяет наличие ключа :value и, если он задан, # использует его значение для определения тега. def initialize( params = {} ) super( params ) tag_handle_opt_param( :value ) do |description| @name.value = description.name @comment.value = description.comment @source_files.value = description.source_files # Обязательно нужно указать, что тег определен. tag_make_defined end end end # Создание тега с подлежащим форматированию значением. to_be_formatted = TagProjectDescription.new( :value => ProjectDescription.new( 'test', 'this is a test project', [ 'first.txt', 'second.txt', 'third.txt' ] ) ) # Отображение содержимого тега на стандартный поток вывода. to_be_formatted.tag_format( ClsRuby::DefaultFormatter.new( STDOUT ) )
Запуск данного примера будет приводить к следующей печати в стандартный поток вывода:
{project-description {name "test" } {comment "this is a test project" } {source-files "first.txt" "second.txt" "third.txt" } }
Классы ClsRuby::OneLineFormatter и ClsRuby::DefaultFormatter получают в конструкторе объект, который играет роль выходного потока. Единственное требование к данному объекту – это поддержка оператора сдвига <<. Такому требованию, например, удовлетворяют Ruby классы IO, String и Array. Что позволяет использовать штатные форматеры ClsRuby как для записи выходного потока в файл, так и в строку (например, для последующего сохранения в БД).
# vim:ts=2:sts=2:sw=2:expandtab:ft=txt:tw=78
Generated with the Darkfish Rdoc Generator 2.