Есть определённый класс задач которые нельзя решить простым изменением настроек, или созданием дополнительного компонента, иногда приходится внедриться в сам код ActiveAdmin. Есть несколько вариантов, можно форкать проект и модифицировать код под себя и если изменение несёт ценность остальным его можно предложить как пулл-реквест, но бывают необходимы совершенно кастомные вещи, здесь приходится прибегать к monkey patching.
Column margin
Есть такой компонент колонки он позволяет развивать страницу таким образом:
columns do column span: 2 do end column span: 1 do end end
Это генерирует вот такой HTML
<div class="columns"> <div class="column" style="width: 66.0%; margin-right: 2%;"></div> <div class="column" style="width: 32.0%;"></div> </div>
Что если я хочу уменьшить margin, 2% съедает очень много места. Большинство подобных проблем решается с помощью стилей, но в данном случае размер захардкожен в методе ActiveAdmin::Views::Columns#margin_size. Здесь нам поможет monkey pathing.
# config/initializers/active_admin.rb ActiveAdmin::Views::Columns.prepend(ActiveAdmin::Views::CustomColumns) # lib/active_admin/views/custom_columns.rb module ActiveAdmin module Views module CustomColumns def margin_size 0.5 end end end end
Есть эпичный ответ про money pathing на stackoverflow. prepend подмешивает наш модуль к классу так что что при поиске метода сначала он будет найден в нашем модуле, далее используя super можно вызвать оригинальную реализацию если она нам нужна. Используя эту технику покажу ещё пару примеров
Вставка <script> тега на страницу
Бывает что нужно использовать какие-то внешние скрипты, их можно вставить в хеадер или футер.
# config/initializers/active_admin.rb ActiveAdmin::Views::Footer.prepend(ActiveAdmin::Views::WithYandexMaps) # lib/active_admin/views/with_yandex_maps.rb module ActiveAdmin module Views module WithYandexMaps def build(*args) super text_node javascript_include_tag(map_js_link, async: true) end end end end
Здесь мы используем базовую реализацию и добавляем ноду с тегом script, в результате получаем:
<div class="footer" id="footer"> <p> Powered by <a href="http://www.activeadmin.info">Active Admin</a> 1.4.3 </p> <script src="http://api-maps.yandex.ru/2.1/?lang=ru_RU" async="async"> </script> </div>
Используем атрибут async для того чтобы браузер не ждал загрузки скрипта и обрабатывал страницу дальше.
Кастомные элементы в header
А теперь вообще безумие. Что если в вашем приложении есть некие домены или tenants, например регионы, и что если админы одного региона не должны работать в другом и даже знать про него, но есть некие супер-админы которые должны знать обо всём и видеть всё с удобным способ переключения. Самое логичное это добавить в заголовку selectbox с возможностью выбора региона.
# config/initializers/active_admin.rb ActiveAdmin::Views::Header.prepend(ActiveAdmin::Views::CustomHeader) # lib/active_admin/views/custom_header.rb module ActiveAdmin module Views module CustomHeader def utility_navigation(*args) insert_tag Arbre::HTML::Ul, class: 'utility-navigation-table' do insert_tag( Arbre::HTML::Form, class: 'current-region-form', action: '/admin/regions/select', method: :patch ) do insert_tag Arbre::HTML::Select, id: 'current-region' do # Регионы доступные текущему админу current_active_admin_user.regions.each do |region| selected = if current_active_admin_user.current_region == region 'selected' end insert_tag( Arbre::HTML::Option, region.name, value: region.id, selected: selected # Помечаем текущий регион ) end end end end super end end end end
Добавляем форму с выпадающим списком в utility_navigation это блок внутри header. И обрабатываем HTTP запрос при переключении:
# app/admin/regions.rb ActiveAdmin.register Region do # ... collection_action :current_region, method: :patch do region = Region.find(params[:region_id]) if admin_panel_user.region_ids.include?(region.id) admin_panel_user.update!(current_region: region) render json: {}, status: 200 else render json: {}, status: 403 end end end
На этот раз пришлось немного повозится со стилями чтобы это нормально выглядело, но результат того стоил:
В прошлую неделю эпизодически работал над адаптацией ActiveAdmin под мобильные устройства, надеюсь в ближайшее время закончить и поделиться рецептом.