Class Index [+]

Quicksearch

Принципы работы с Cls. Передача параметров в конструкторы тегов

Введение

Для задания параметров конструктуру тегов в ClsRuby используется единственный аргумент типа Hash, который содержит пары <ключ,значение>. Синтаксис Ruby позволяет задавать этот аргумент как будто используются именованные аргументы в других языках программирования:

root = ClsRuby::TagNoValue.new :name => 'root', :mandatory => true

здесь :name и :mandatory являются ключами единственного аргумента типа Hash для объекта ClsRuby::TagNoValue.

Использование единственного аргумента типа Hash позволяет легко расширять параметры тега в производных классах. Например, тег ClsRuby::TagNoValue поддерживает параметры класса ClsRuby::Tag и, в дополнение к этому, распознает собственный ключ :once.

Подход с аргументом типа Hash так же позволяет задавать в производных классах необходимые умолчания. Во-первых, с помощью значения по умолчанию для аргумента:

class MyTag < ClsRuby::Tag
  def initialize( params = { :mandatory = true } )
    super( params )
    ...
  end
end

В таком случае, если при создании объекта MyTag не будет передано аргументов, то в базовый класс уйдет объект Hash со значением {:mandatory=>true}.

Во-вторых, значения по умолчанию легко комбинировать с явно заданными пользователем параметрами:

class MyTag < ClsRuby::Tag
  def initialize( params = {} )
    super( { :name => 'root', :mandatory => false }.merge( params ) )
    ...
  end
end

В этом случае, если пользователь явно не задал ключи :name и :mandatory, то будут взяты соответствующие им значения по умолчанию. Если же пользователь задал эти ключи в аргументе params, то вместо значений по умолчанию будут использоваться заданные пользователем значения.

Следствием такого решения является возможность использовать методы ClsRuby::Tag#child_tag, Tag#mandatory_child_tag и Tag#default_tag_params. Принцип их действия основан на том, что параметры дочерних тегов сохраняются в виде объекта Hash, а затем используются для создания и инициализации дочерних тегов.

Параметры тега по умолчанию

Вместо использования метода Hash#merge для задания параметров по умолчанию:

def initialize( params )
  super( { :name => 'root' }.merge( params ) )
  ...
end

можно воспользоваться методом ClsRuby::Tag#default_tag_params, что делает описание тега более декларативным:

class MyTag < ClsRuby::Tag
  default_tag_params :name => 'root'
  ...
end

Еще одной важной особенностью метода ClsRuby::Tag#default_tag_params является то, что в случае наследования параметры по умолчанию накапливаются:

require 'cls-ruby'
require 'cls-ruby/tag'

class MyBase < ClsRuby::Tag
  default_tag_params :name => 'root'
end

class MyDerived < MyBase
  default_tag_params :mandatory => true
end

class MyNextDerived < MyDerived
  default_tag_params :once => true

  def show_params
    p tag_params
  end
end

t = MyNextDerived.new
t.show_params

что дает в результате:

{:name=>"root", :mandatory=>true, :once=>true}

Стандартные идентификаторы

Класс ClsRuby::Tag обрабатывает следующие ключи в аргументах конструктора:

name

имя тега;

mandatory

признак обязательности/необязательности тега;

owner

ссылка на родительский тег. Если эта ссылка задана, то конструктор автоматически вызывает tag_add для родительского тега.

Если тег должен содержать какое-либо значение (например, как в случае с ClsRuby::TagScalar), то это значение может быть задано в конструкторе с помощью ключа :value.

Специализированные теги могут поддерживать собственные ключи (например, :format для ClsRuby::TagScalar и :once для ClsRuby::TagNoValue). Для того, чтобы определить список поддерживаемых тегом ключей необходимо обратиться к описанию данного тега.

Доступ к параметрам тега

Когда параметры тега попадают в конструктор базового класса ClsRuby::Tag, то они объединяются со списком параметров по умолчанию (заданных посредством default_tag_params). Поэтому для получения доступа к полному списку параметров тега необходимо использовать метод ClsRuby::Tag#tag_params, т.к. он возвращает ссылку на Hash с результирующим списком параметров.

Доступ к необязательным параметрам тега

В связи с тем, что легко забыть про наличие параметров по умолчанию, легко можно написать неправильный код обработки необязательных параметров в конструкторе собственного тега. Например, если нужно обрабатывать тег :value для того, чтобы сразу сделать тег определенным:

def initialize( params = {} )
  super( params )

  value = params.fetch( :value )
  if value
    ... # Обработка
  end
end

Ошибка здесь в том, что здесь используется значение аргумента конструктора, но полностью игнорируются возможные значения по умолчанию. Правильный код должен использовать метод tag_params:

def initialize( params = {} )
  super( params )

  value = tag_params.fetch( :value )
  if value
    ... # Обработка
  end
end

либо, что более декларативно, использовать метод Tag#tag_handle_opt_param:

def initialize( params )
  super( params )

  tag_handle_opt_param( :value ) do |v|
    ...
    tag_make_defined
  end
end

# vim:ts=2:sts=2:sw=2:expandtab:ft=txt:tw=78

[Validate]

Generated with the Darkfish Rdoc Generator 2.