Содержание ЦельСгенерированные файлыКак экземпляр нашей модели связывается с экземпляром ActionText в таблице action_text_rich_textsКак сохраняются файлы/рисунки в записяхИтого Возможность создания, хранения и редактирования текста с рисунками, прикрепленными файлами - частая задача. Суть задачи - сделать удобный инструмент контент-менеджеру для добавления текстовых данных на сайт. В Ruby on Rails для этой цели есть модуль ActionText с соответствующей документацией, который добавляет возможность редактирования текста в Rails. Он включает в себя редактор Trix. Редактор написан на JavaScript, запускается на стороне клиента (браузера) и рисует довольно дружественный интерфейс. Создание используемой ниже в примерах модели Note, его контроллера, представлений (show/edit/new.html.erb), роутинга и других базовых действий, связанных с этой моделью, выходит за рамки этой статьи. Для начала работы с модулем Action Text устанавливаем нужные библиотеки командой: После выполнения этой команды вы увидите множество измененных и сгенерированных файлов: Хорошо бы понимать, что происходит. Почитаем файлы и узнаем: Предыдущим действием мы установили гем image_processing. Этот пакет нужен, чтобы обрабатывать (сжимать, изменять размер) и загружать рисунки в добавляемый контент. Этот гем использует либо ImageMagick/GraphicsMagick, либо libvips. В Gemfile.lock можно посмотреть установленные библиотеки-зависимости для image_processing. Нужность их описана здесь.  Для работы этого гема я добавила в config/application.rb строку (из описания класса ActiveStorage::Variant: Здесь импортировали JavaScript библиотеки trix и @rails/actiontext. В этом файле создаются соответствия библиотек и сгенерированных js-файлов и отдаются клиенту в соответствии c этими названиями. Тут добавился JavaScript код для Trix. В DevTools во вкладке Debugger можно посмотреть эти соответствия. Пример на рисунке ниже, где   1 - imports,   2 - js - файлы,   3 - Trix редактор в браузере. Напомню, что для генерации компилированных css/js файлов используется команда (см. The Asset Pipeline:  Вроде бы обычный css файл, но мы видим, что при генерации html используется элемент action-text-attachment, которого нет в списке html-элементов, но генерируется html-элемент <action-text-attachment> с CustomElementRegistry. В этом файле описан класс миграции, создающий таблицы в префиксом active_storage_: * active_storage_blobs * active_storage_attachments * active_storage_variant_records Более подробно эти таблицы описаны в документации Active Storage Overview.  Здесь написаны какие поля создадутся в вышесказанных таблицах, ограничения полей по уникальности первичных и внешних ключей. Например, в таблице active_storage_attachments создаются поля: name с ограничением, что он не должен быть пустым, record_type, record_id с типом bigint, который с record_type создаются с опцией polymorphic: true (см. Active Record Migrations References), blob_id с типом bigint, ссылающийся на запись id из таблицы active_storage_blobs, имеющий ограничение внешнего ключа по blob_id, создается ограничение на уникальность комбинации полей record_type, record_id, name, blob_id. В этом файле описан класс миграции, создающий таблицы в префиксом action_text_ (там всего одна таблица): action_text_rich_texts В этой таблице в поле body и будет хранится контент в виде html. Все ссылки на рисунки и файлы будут сгенерированы при создании этого контента и сразу встроены в текст.  После запуска миграции командой bin/rails db:migrate в итоге должны появится таблицы в вашей базе данных.  Здесь вставляется body, который сохранен в виде html, из таблицы action_text_rich_texts.  В DevTools сохраненный контент с рисунком выглядит таким образом: В этом html куске страницы рисуется предпросмотр файла и изображение, данные о которой сохранены в таблице active_storage_blobs. Описание к загруженному через Trix-редактор рисунку хранится как часть текста в таблице action_text_rich_texts. В _blob.html.erb я добавила возможность скачать файл, в отличие от файла по умолчанию. В модели я пишу ассоциацию has_rich_text. Затем, при создании экземпляра в контроллере в разрешенные параметры добавляю body: Через has_rich_text в модели работает соответствующий метод из модуля ActionText::Attribute. Код этого метода с репозитория rails читаю так: Создаются методы для экземпляра модели: предикат body?, сеттер и геттер для этого поля. Создается ассоциация rich_text_body с именем класса ActionText::RichText, с именем поля name. as: :record - признак полиморфной связи, что также видно было в миграции при созданий таблицы action_text_rich_texts. Эта ассоциация инверсная, то есть из экземпляра модели ActionText::RichText можно получить значение этого поля через вызов метода record.  Итого, видно, что note.body и поиск экземпляра ActionText::RichText по известному id ссылаются на одну и ту же запись, что и показывает, что опция inverse_of работает ожидаемо. При создании новой записи в Trix-редакторе, нажимая на значок скрепки вы можете добавить файл. При выборе оного, например, рисунка, в консоли, где запущен сервер, вы можете увидеть, что делается запрос POST "/rails/active_storage/direct_uploads", который обрабатывается ActiveStorage::DirectUploadsController#create с параметрами: В ActiveStorage::DirectUploadsController#create происходит сохранение нужных параметров этого файла. В консоли выглядит таким образом: По умолчанию файлы хранятся на локальном диске, описанный как local в файле config/storage.yml и настроенный по умолчанию. В этом случае service будет Disk. Из значение key сохраненного файла генерируется название файла и его папка и все папки с этими файлами хранятся в папке storage. Когда контент-менеджер добавляет текст, нажимает на кнопку Опубликовать и сохраняет запись. Ссылка на файл сохраняется прямо в теле rich_text. Делается запись в таблицу active_storage_attachments, которая сохраняет связь между таблицами action_text_rich_texts и active_storage_blobs.  В таблице active_storage_attachments: в поле record_id сохраняется id записи из таблицы action_text_rich_texts,  в поле record_type сохраняется название модуля/класса записи из таблицы action_text_rich_texts, в поле blob_id сохраняется id файла/рисунка из таблицы active_storage_blobs, в поле name сохраняется тип файла/рисунка. Охватила: Описание файлов, генерируемых командой bin/rails action_text:install Таблицы, создаваемые в базе данных, какие данные сохраняются в этих таблицах. Встраивание Trix-редактора в нужную страницу через ассоциацию has_rich_text. Способ сохранения файлов AсtionText по умолчанию. На этом закончу. Очевидно, это еще не все. Далее надо сделать: Выбор и настройка сервиса для сохранения файлов не локально. Использование пакета libvips вместо ImageMagick. Пишут, что libvips новее и быстрее. Cохранение нескольких вариантов изображений для разного размера экранов устройств с использованием таблицы active_storage_variant_records. В атрибуте has_many_attached :embeds класса ActionText::RichText я не нашла variant. Удовольствия вам от программирования, друзья! Инженер