Дескриптор атрибутов объектов

Дескриптор атрибута объекта (или дескриптор поля, если хотите) – это хеш-структура, описывающая полный набор параметров и свойств, описывающих поле объекта, его внешний вид в форме редактирования объекта и связь с определенным полем в БД (для полей, описанных в required_properties).

Полный массив атрибутов возвращает метод structure любого Contenido-объекта. Собирается этот список из полей, описанных в методах required_properties дескриптора таблицы и extra_properties объекта Contenido. Причем, атрибуты, описанные в extra_properties, накладываются на список атрибутов, описанных в required_properties, переписывая свойства основных полей. Сопоставление ведется по значению attr – названию атрибута, на основе которого строится соответствующий метод.

Пример описания списка основных атрибутов:

sub required_properties
{
        my $self = shift;

        my @parent_properties = $self->SUPER::required_properties;
        return (
                @parent_properties,
                {
                        'attr'          => 'uid',
                        'type'          => 'integer',
                        'rusname'       => 'Идентификатор пользователя',
                        'db_field'      => 'uid',
                        'db_type'       => 'integer',
                        'db_opts'       => "not null default 0",
                },
                {
                        'attr'          => 'ext_id',
                        'type'          => 'integer',
                        'rusname'       => 'Внешний ID новости',
                        'db_field'      => 'ext_id',
                        'db_type'       => 'integer',
                        'db_opts'       => "default 0",
                },
                {
                        'attr'          => 'subscribe',
                        'type'          => 'checkbox',
                        'rusname'       => 'Включить в рассылку?',
                        'db_field'      => 'subscribe',
                        'db_type'       => 'integer',
                        'db_opts'       => "not null default 0",
                        'default'       => 0,
                },
                {
                        'attr'          => 'votes',
                        'type'          => 'integer',
                        'rusname'       => 'Кол-во голосов',
                        'db_field'      => 'votes',
                        'db_type'       => 'integer',
                        'default'       => 0,
                },
                {
                        'attr'          => 'value',
                        'type'          => 'integer',
                        'rusname'       => 'Сумма голосов',
                        'db_field'      => 'value',
                        'db_type'       => 'integer',
                        'default'       => 0,
                },
                {
                        'attr'          => 'rating',
                        'type'          => 'integer',
                        'rusname'       => 'Рейтинг',
                        'db_field'      => 'rating',
                        'db_type'       => 'integer',
                        'default'       => 0,
                },

        );
}

Пример описания экстра-полей в объекте с переопределением:

sub extra_properties
{
        return (
                { 'attr' => 'dtime',            'type' => 'datetime',           'rusname' => 'Дата', },
                { 'attr' => 'uid',            'type' => 'pickup',           'rusname' => 'Пользователь',
                                lookup_opts => { class => 'users::Profile', search_by => 'name' },
                },
                { 'attr' => 'abstr',            'type' => 'text',               'rusname' => 'Аннотация', rows => 5 },
                { 'attr' => 'body',             'type' => 'wysiwyg',            'rusname' => 'Полный текст документа', rows => 45 },
                { 'attr' => 'url',              'type' => 'url',                'rusname' => 'Ссылка на оригинал' },
                { 'attr' => 'source_name',      'type' => 'string',             'rusname' => 'Источник / исходящие данные' },
                { 'attr' => 'source_url',       'type' => 'string',             'rusname' => 'URL источника' },
                { 'attr' => 'icon',             'type' => 'image',              'rusname' => 'Иконка', preview => ['240x240'], crop => ['150x150'] },
                { 'attr' => 'pictures',         'type' => 'images',             'rusname' => 'Список изображений', preview => ['240x240'], crop => ['150x150'] },
        )
}

В данном примере для атрибута dtime (унаследован от SQL::DocumentTable) переопределена подпись (rusname) поля в форме редактирования. А для атрибута uid переопределен тип и добавлена структура, необходимая для обработчика данного типа (pickup).

Итоговая структура, возвращаемая методом structure для поля dtime, будет выглядеть так:

                {
                        'attr'          => 'dtime',
                        'type'          => 'datetime',
                        'rusname'       => 'Дата',
                        'column'        => 1,
                        'db_field'      => 'dtime',
                        'db_type'       => 'timestamp',
                        'db_opts'       => 'not null default now()',
                        'default'       => 'CURRENT_TIMESTAMP',
                },

Итоговая структура, возвращаемая методом structure для поля uid, будет выглядеть так:

                {
                        'attr'          => 'uid',
                        'type'          => 'pickup',
                        'rusname'       => 'Идентификатор пользователя',
                        'lookup_opts'   => {
                                'class'         => 'users::Profile',
                                'search_by'     => 'name',
                       },
                        'db_field'      => 'uid',
                        'db_type'       => 'integer',
                        'db_opts'       => "not null default 0",
                },

Все атрибуты, возвращаемые методом extra_properties и не имеющие соответствия среди основных полей, добавляются в конец списка метода structure. Их содержимое при сохранении объекта в БД собирается в единую структуру, сериализуется (в момент написания статьи методом сериализации выбран json) и складывается в поле data.

При инициализации объекта из БД, происходит обратный процесс: десериализация и разбрасывание значений по атрибутам.

Общий вид описания атрибута

Параметры, участвующие в описании атрибута, по своей принадлежности разделяются на:

  • параметры самого атрибута;
  • параметры связи с базой данных;
  • параметры, управлящие обработчиком типа;
  • пользовательские параметры.

Попробуем расписать пулю на примере уже описанного uid:

                {
## Описание атрибута
                        'attr'          => 'uid',     # название атрибута
                        'type'          => 'pickup',     # тип атрибута
                        'rusname'       => 'Идентификатор пользователя',      # название поля в админке
## Параметры связи с БД
                        'db_field'      => 'uid',     # название поля в БД
                        'db_type'       => 'integer',      # тип поля в БД
                        'db_opts'       => "not null default 0",     # опции поля в БД
                        'default'      => 'NULL',     # значение по умолчанию, подставляемое в SQL-запрос; также используется для формы редактирования некоторыми обработчиками типов
## Параметры, управляющие обработчиком
                        'lookup_opts'   => {    # параметры запроса к get_documents для поиска и подбора связанных документов
                                'class'         => 'users::Profile',
                                'search_by'     => 'name',
                       },
                },

.

Типы данных

В дескрипторе атрибута поле type

Практический пример. Расширение свойств SQL::DocumentTable
Документы, построенные на собственных (кастомных) таблицах
Связи, построенные на собственных (кастомных) таблицах
Дескриптор атрибутов объектов