Конструкция панели Rails: одно действие контроллера на div

Я внедряю панель управления в качестве относительного новичков Rails (больше из парня инфраструктуры). Панель инструментов будет состоять из нескольких страниц, каждая страница которых будет содержать несколько диаграмм/таблиц и т.д. Для модульности я хочу, чтобы было как можно проще добавить новые диаграммы или изменить представления данных.

Скажите, что на одной странице есть 5 разных диаграмм. Я мог бы заставить контроллер выполнить 5 отдельных поисков данных, провести все соответствующие данные в переменных экземпляра и отобразить 5 частичных, каждый из которых касается подмножеств данных. Но кажется более модульным иметь одно действие "индексатора", у рендера которого есть куча div, а для каждого div есть другое действие контроллера, которое выполняет поиск данных и имеет связанный с ним вид, частично отвечающий за управление представлением этих данных в пределах div.

Итак, если я показываю страницу панели инструментов веб-сайта, которая имеет два графика, website/index будет использовать website/graph1 и website/graph2 для поиска данных для каждого, а затем _graph1.html.erb и _graph2.html.erb будет использовать контроллер данные для заполнения divs "graph1" и "graph2" и т.д.

Это правильный дизайн, и если да, то какой самый простой способ это сделать? У меня есть приближение, используя remote_function с :action => "graph1", чтобы заполнить divs, но я не на 100% доволен этим. Я подозреваю, что мне не хватает чего-то проще, чем Rails сделает для меня.

Ответ 1

Версия 1:

Простой метод, который я фактически использовал в производстве: iframes.

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

Если вы просто отпустите iframe src'd для действия с представлением контроллера, у вас есть очень простое решение, которое не требует прямого взаимодействия между контроллерами.

Pro:

  • dead easy
  • работает с существующими действиями шоу и т.д.
  • может быть даже быстрее, в зависимости от экономии с параллельными или последовательными запросами и загрузкой памяти и т.д.

Минусы:

  • вы не всегда можете легко сохранить страницу вместе с тем, что есть
  • iframes вырвется из пространства имен javascript главной страницы, поэтому, если они потребуют этого, вам может потребоваться предоставить им свой минималистский макет; они также не смогут влиять на окружающие страницы вне их iframe
  • может быть медленнее, в зависимости от времени пинга и т.д.
  • потенциал n + 1 ошибка эффективности, если у вас много таких модулей на странице

Версия 2:

Сделайте то же самое, используя JS-вызовы, чтобы заменить div частичным, à la:

<div id="placeholder">
<%= update_page {|page| page['placeholder'].replace with some partial call here } %>

То же, что и выше, кроме:

Pro:

  • не блокирует его в iframe, поэтому разделяет контекст JS и т.д.
  • позволяет лучше обрабатывать случаи сбоя

Con:

  • требуется JS и разделители; немного сложнее

Версия 3:

Вызвать целую кучу частичных данных. Сложно это сделать, когда вы говорите о таких вещах, как панели мониторинга, где отдельные модули имеют значительную логику установки.

Существуют различные способы обойти это, превратив эти вещи в "миксины" или тому подобное, но IMO они немного глупы.

ETA: способ сделать это через mixins - это создать то, что по существу является файлом библиотеки, который реализует функции настройки вашего контроллера модуля, включать в себя то, где используется что-то, что вызывает их, и вызвать их.

Однако это имеет свои недостатки:

  • вам нужно знать, какие действия контроллера верхнего уровня будут приводить к страницам, которые включают эти модули (что вам может быть нелегко, если они действительно виджетные вещи, которые могут появляться повсюду, например, зависимые от пользователя)
  • он не действует как полноценный контроллер
  • он все еще смешивает много логики, где ваша вещь должна знать о вещах, которые она держит.
  • вы не можете легко разделить его на свой собственный контроллер, потому что он должен быть в библиотечном файле /mixin

Можно вызвать методы в одном контроллере с другого контроллера. Тем не менее, это большая боль в заднице и крупный клоч. Единственный раз, когда вам стоит подумать об этом, заключается в том, что: a) они оба независимо необходимы контроллерам в своих правах, и b) он должен полностью функционировать на задней панели.

Мне приходилось делать это один раз - прежде всего потому, что рефакторинг причины был даже БОЛЬШЕ боли - и я обещаю, что вы не хотите туда идти, если только не придется.

Резюме

Лучший метод IMHO - это первый, если у вас достаточно сложные вещи, для которых требуется значительная настройка - простой iframe, который отображает модуль, передавая параметр, чтобы сообщить ему использовать макет ультраминимализма (только заголовки CSS + JS), поскольку он не отображается как его собственная страница.

Это позволяет вам сохранять вещи полностью независимыми, работать более или менее, как если бы они были совершенно обычными контроллерами (кроме настройки макета), сохраняли обычные маршруты и т.д.

Если вам НЕ нужна значительная настройка, просто используйте частичные и передайте все, что им нужно, в качестве локальной переменной. Это начнет становиться хрупким, если вы столкнетесь с такими вещами, как ошибки эффективности n + 1, хотя...

Ответ 3

Вы можете достичь этого, используя

render_output = render: action = > "graph2"

Но я лично, вероятно, перенесет код в общий помощник или напишу вам собственную "lib" в каталоге lib, чтобы повторно использовать код с общим шаблоном. Помните, что если вы не измените файл route.rb, любой открытый общедоступный метод доступен

/контроллер/действие/: Идентификатор

Также не забудьте отключить макет для функции: layout = > nil (или указать в верхней части макета контроллера "graph",: except = > [ "graph2" ]

Приветствия

Christian

Ответ 4

Я не знаю каких-либо специальных трюков Rails для достижения этого, не используя AJAX в том, как вы начертили.

Самый простой способ получить модульность, которую вы ищете, состоит в том, чтобы поместить эти части кода контроллера в отдельные методы (например, set_up_graph1_data, set_up_graph2_data и т.д.), которые вы просто вызываете из своего действия index для настройки переменные для представления.

Вы можете поместить эти методы в ApplicationController, если вы хотите, чтобы они были доступны для нескольких контроллеров.

В качестве дополнительной заметки на раннем этапе Rails использовала функцию "компоненты", которая позволила бы вам делать именно то, что вы просите здесь, без использования AJAX. С вашего взгляда вы можете просто выполнить другое действие контроллера, встроенное. Однако эта функция была удалена по соображениям производительности и дизайна.