diff --git "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" index b42e3d7..3c3d21b 100644 --- "a/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" +++ "b/docs/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.md" @@ -17,7 +17,11 @@ ### Колонки ```bsl - +// Возвращает таблицу колонок модели. +// +// Возвращаемое значение: +// ТаблицаЗначений - Колонки модели, только для чтения. +// Функция Колонки() Экспорт ``` @@ -28,17 +32,6 @@ Функция ПодчиненныеТаблицы() Экспорт ``` -### Служебный_Колонки - -```bsl -// @internal -// TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, -// вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения -// в объект данные. -// -Функция Служебный_Колонки() Экспорт -``` - ### Служебный_ИмяТаблицы ```bsl diff --git "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" index 1eee606..e2af1cf 100644 --- "a/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" +++ "b/src/internal/\320\234\320\276\320\264\321\203\320\273\320\270/\320\236\320\261\321\200\320\260\320\261\320\276\321\202\320\272\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\271.os" @@ -93,7 +93,8 @@ ); ОбъектМоделиЭлементКоллекции.Служебный_ИмяТаблицы(ПодчиненнаяТаблица.ИмяТаблицы); - КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Служебный_Колонки(); + // Колонки модели только для чтения, но этот объект модели только что создан и еще никому не отдан. + КолонкиОбъектаМодели = ОбъектМоделиЭлементКоллекции.Колонки(); КолонкаKey = КолонкиОбъектаМодели.Найти("key", "ИмяКолонки"); КолонкаKey.ТипКолонки = ТипКолонкиКлюч; diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index ec6c2cd..c570487 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -8,20 +8,25 @@ Перем Колонки; Перем ПодчиненныеТаблицы; // TODO: Первичный ключ из нескольких полей? +// ФиксированнаяСтруктура. Перем Идентификатор; +// Соответствие типа колонки модели его ОписаниюТипов. Строится в конструкторе и дальше только читается. +Перем ОписанияТиповКолонок; + Перем МодельДанных; Перем Рефлектор; Процедура ПриСозданииОбъекта(ПТипСущности, ПМодельДанных) - + МодельДанных = ПМодельДанных; ТипСущности = ПТипСущности; + ОписанияТиповКолонок = СоответствиеТиповМоделиОписанийТипов(); ЗаполнитьКолонки(); ЗаполнитьПодчиненныеТаблицы(); Рефлектор = Новый Рефлектор; - + КонецПроцедуры Функция ИмяТаблицы() Экспорт @@ -32,30 +37,26 @@ Возврат ИсточникиДанных; КонецФункции +// Возвращает таблицу колонок модели. +// +// Возвращаемое значение: +// ТаблицаЗначений - Колонки модели, только для чтения. +// Функция Колонки() Экспорт - Возврат Колонки.Скопировать(); + Возврат Колонки; КонецФункции Функция ПодчиненныеТаблицы() Экспорт Возврат ПодчиненныеТаблицы.Скопировать(); КонецФункции -// @internal -// TODO: вынести отсюда. Возможно стоит разработать отдельный служебный билдер Объекта модели, -// вытащив заполнение из конструктора в этот билдер, а в конструктор передавать уже готовые для сохранения -// в объект данные. -// -Функция Служебный_Колонки() Экспорт - Возврат Колонки; -КонецФункции - // @internal Процедура Служебный_ИмяТаблицы(ПИмяТаблицы) Экспорт ИмяТаблицы = ПИмяТаблицы; КонецПроцедуры Функция Идентификатор() Экспорт - Возврат Новый ФиксированнаяСтруктура(Идентификатор); + Возврат Идентификатор; КонецФункции Функция МодельДанных() Экспорт @@ -72,10 +73,9 @@ КонецФункции Функция ПолучитьПриведенноеЗначениеПоля(Сущность, ИмяПоля) Экспорт + Колонка = КолонкаПоИмениПоля(ИмяПоля); ЗначениеПоля = ПолучитьЗначениеПоля(Сущность, ИмяПоля); - - Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); - + Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда ОбъектМоделиСсылки = МодельДанных.Получить(Колонка.ТипСсылки); Если ЗначениеПоля = Неопределено Тогда @@ -94,8 +94,8 @@ Процедура УстановитьЗначениеКолонкиВПоле(Сущность, ИмяКолонки, ЗначениеПоля) Экспорт - Колонка = Колонки().Найти(ИмяКолонки, "ИмяКолонки"); - + Колонка = КолонкаПоИмениКолонки(ИмяКолонки); + Если Колонка.ТипКолонки = ТипыКолонок.Ссылка Тогда УстанавливаемоеЗначениеПоля = ЗначениеПоля; Иначе @@ -112,11 +112,27 @@ Функция ПривестиЗначениеПоля(ЗначениеПоля, ИмяПоля) Экспорт - Колонка = Колонки().Найти(ИмяПоля, "ИмяПоля"); + Колонка = КолонкаПоИмениПоля(ИмяПоля); Возврат ВыполнитьПриведениеЗначения(Колонка, ЗначениеПоля); КонецФункции +Функция КолонкаПоИмениПоля(Знач ИмяПоля) + Колонка = Колонки.Найти(ИмяПоля, "ИмяПоля"); + Если Колонка = Неопределено Тогда + ВызватьИсключение СтрШаблон("В модели сущности %1 нет поля %2", ТипСущности, ИмяПоля); + КонецЕсли; + Возврат Колонка; +КонецФункции + +Функция КолонкаПоИмениКолонки(Знач ИмяКолонки) + Колонка = Колонки.Найти(ИмяКолонки, "ИмяКолонки"); + Если Колонка = Неопределено Тогда + ВызватьИсключение СтрШаблон("В модели сущности %1 нет колонки %2", ТипСущности, ИмяКолонки); + КонецЕсли; + Возврат Колонка; +КонецФункции + Функция ПолучитьЗначениеПоля(Сущность, ИмяПоля) Экспорт ЗначениеПоля = Рефлектор.ПолучитьСвойство(Сущность, ИмяПоля); Возврат ЗначениеПоля; @@ -173,6 +189,13 @@ ЗаполнитьЗначенияСвойств(Колонки.Добавить(), ДанныеОКолонке); КонецЦикла; + Колонки.Индексы.Добавить("ИмяПоля"); + Колонки.Индексы.Добавить("ИмяКолонки"); + + Если Идентификатор <> Неопределено Тогда + Идентификатор = Новый ФиксированнаяСтруктура(Идентификатор); + КонецЕсли; + КонецПроцедуры Процедура ЗаполнитьПодчиненныеТаблицы() @@ -300,10 +323,8 @@ КонецЕсли; ОбработанноеЗначение = Значение; - - КартаОписанийТипов = СоответствиеТиповМоделиОписанийТипов(); - - ОписаниеТипов = КартаОписанийТипов.Получить(Колонка.ТипКолонки); + + ОписаниеТипов = ОписанияТиповКолонок.Получить(Колонка.ТипКолонки); Если ОписаниеТипов = Неопределено Тогда ВызватьИсключение "Неизвестный тип колонки " + Колонка.ИмяКолонки; КонецЕсли; diff --git "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" index 1426b4b..619d676 100644 --- "a/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" +++ "b/tests/\320\236\320\261\321\212\320\265\320\272\321\202\320\234\320\276\320\264\320\265\320\273\320\270.os" @@ -41,5 +41,138 @@ Ожидаем.Что(ИсточникиДанных, "Объект модели имеет источники данных").ИмеетДлину(2); Ожидаем.Что(ИсточникиДанных[0], "Первый источник данных имеет корректное имя").Равно("Основной"); Ожидаем.Что(ИсточникиДанных[1], "Второй источник данных имеет корректное имя").Равно("Дополнительный"); - + +КонецПроцедуры + +// Колонки() отдает саму таблицу модели, без копии на каждое обращение. +&Тест +Процедура КолонкиОтдаютТаблицуМодели() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Ожидаем.Что(ОбъектМодели.Колонки(), "Повторное обращение отдает ту же таблицу") + .Равно(ОбъектМодели.Колонки()); + +КонецПроцедуры + +// Колонка ищется по имени поля и по имени колонки - по каждому из них есть индекс. +&Тест +Процедура КолонкиИндексированыПоИменам() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Индексы = Новый Массив; + Для Каждого Индекс Из ОбъектМодели.Колонки().Индексы Цикл + Индексы.Добавить(Строка(Индекс)); + КонецЦикла; + + Ожидаем.Что(Индексы, "Есть индекс по имени поля").Содержит("ИмяПоля"); + Ожидаем.Что(Индексы, "Есть индекс по имени колонки").Содержит("ИмяКолонки"); + +КонецПроцедуры + +// Так ОбработкаКоллекций донастраивает типы колонок объекта модели элемента коллекции: правка +// таблицы колонок видна и поиску колонки, и приведению значения. +&Тест +Процедура ИзменениеКолонокМеняетПриведение() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки = ТипыКолонок.Целое; + + Ожидаем.Что(ОбъектМодели.Колонки().Найти("Имя", "ИмяПоля").ТипКолонки, "Модель видит правку") + .Равно(ТипыКолонок.Целое); + Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля("12", "Имя"), "Поле приводится по новому типу") + .Равно(12); + + Автор = Новый Автор; + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Имя", "12"); + Ожидаем.Что(Автор.Имя, "Колонка устанавливается по новому типу").Равно(12); + + Автор.Имя = "34"; + Ожидаем.Что(ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Автор, "Имя"), "Значение поля приводится по новому типу") + .Равно(34); + +КонецПроцедуры + +// Поле ищется по имени поля, колонка - по имени колонки: у поля ВтороеИмя колонка Фамилия. +&Тест +Процедура ПолеИКолонкаИщутсяКаждыйПоСвоемуИмени() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Автор = Новый Автор; + ОбъектМодели.УстановитьЗначениеКолонкиВПоле(Автор, "Фамилия", "Иванов"); + Ожидаем.Что(Автор.ВтороеИмя, "Колонка Фамилия пишется в поле ВтороеИмя").Равно("Иванов"); + + Ожидаем.Что(ОбъектМодели.ПривестиЗначениеПоля(5, "ВтороеИмя"), "Поле ВтороеИмя приводится к строке") + .Равно("5"); + Ожидаем.Что(ОбъектМодели.ПолучитьПриведенноеЗначениеПоля(Автор, "ВтороеИмя"), "Поле ВтороеИмя читается") + .Равно("Иванов"); + КонецПроцедуры + +&Тест +Процедура НеизвестноеПолеНеПриводится() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Параметры = Новый Массив; + Параметры.Добавить(1); + Параметры.Добавить("НетТакогоПоля"); + + Ожидаем.Что(ОбъектМодели) + .Метод("ПривестиЗначениеПоля", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет поля НетТакогоПоля"); + +КонецПроцедуры + +&Тест +Процедура НеизвестнаяКолонкаНеУстанавливается() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Параметры = Новый Массив; + Параметры.Добавить(Новый Автор); + Параметры.Добавить("НетТакойКолонки"); + Параметры.Добавить(1); + + Ожидаем.Что(ОбъектМодели) + .Метод("УстановитьЗначениеКолонкиВПоле", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет колонки НетТакойКолонки"); + +КонецПроцедуры + +&Тест +Процедура НеизвестноеПолеНеЧитается() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Параметры = Новый Массив; + Параметры.Добавить(Новый Автор); + Параметры.Добавить("НетТакогоПоля"); + + Ожидаем.Что(ОбъектМодели) + .Метод("ПолучитьПриведенноеЗначениеПоля", Параметры) + .ВыбрасываетИсключение("В модели сущности Автор нет поля НетТакогоПоля"); + +КонецПроцедуры + +// Идентификатор отдается неизменяемым: правка результата невозможна и модель не меняет. +&Тест +Процедура ИдентификаторНеизменяем() Экспорт + + ОбъектМодели = НовыйОбъектМоделиАвтора(); + + Ожидаем.Что(ТипЗнч(ОбъектМодели.Идентификатор()), "Идентификатор - фиксированная структура") + .Равно(Тип("ФиксированнаяСтруктура")); + Ожидаем.Что(ОбъектМодели.Идентификатор(), "Повторное обращение отдает тот же идентификатор") + .Равно(ОбъектМодели.Идентификатор()); + +КонецПроцедуры + +Функция НовыйОбъектМоделиАвтора() + ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "Автор.os"), "Автор"); + ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures", "СущностьБезГенерируемогоИдентификатора.os"), "СущностьБезГенерируемогоИдентификатора"); + Возврат Новый ОбъектМодели(Тип("Автор"), Неопределено); +КонецФункции