Попытка динамически загружать код для переопределения виджета - это неправильный подход. Вместо этого метод widget
должен решить, какая версия должна отображаться по запросу по запросу. Прежде чем мы рассмотрим некоторые способы сделать это, давайте объясним, почему переопределение модуля не работает.
ApplicationController
загружается, когда приложение Rails запускается. Это автоматически включает в себя модуль ApplicationHelper
, который определяет метод widget
. AdminHelper
не загружен из-за установки config.action_controller.include_all_helpers
- установив его на false
. Рельсы будут загружать только хелпер с тем же именем, что и контроллер.
Когда обычный пользователь вызывает метод widget
, возвращается строка "widget"
. Но , как только администратор посещает сайтinclude_backend_helpers
обратный вызов загружает ваш модуль AdminHelper
, переопределяя метод widget
. Администратор получает строку "admin-widget"
, а также каждый будущий посетитель сайта! Метод widget
не дифференцируется в зависимости от типов пользователей.
Вы можете решить эту проблему, перезагрузив ApplicationController
после каждого запроса, но это требует времени и сделает производительность отстойной. Вы might be able to unload the module, но это похоже на подход, чреватый трудностями. Кроме того, можно попробовать перезагрузить помощник по каждому запросу:
def include_backend_helpers
if admin_signed_in?
self.class.helper "admin/backend"
else
self.class.helper "user/backend"
end
end
Но я не уверен, что будет работать, и я бы не рекомендовал его.
Вместо этого кажется, что задача виджета - решить, что подходит для отображения. Например, если это компонент навигации, он должен быть достаточно умным, чтобы показывать только ссылки администратора. Вы все еще можете разбить его на отдельные методы:
module ApplicationHelper
def widget
if admin_signed_in?
user_widget
else
admin_widget
end
end
private
def user_widget
"widget"
end
def admin_widget
"admin-widget"
end
end
Вы можете использовать аналогичный подход с Rails обертонов - вы могли бы иметь _navigation.html.erb
частичные, который включает в себя либо _user_navigation.html.erb
или _admin_navigation.html.erb
, основанные на admin_signed_in?
.Ваше мнение включает в себя «<% = визуализировать» навигацию «%>» и не беспокоиться о внутренних деталях.
Если у вас достаточно кода, что вышеприведенное начинает казаться громоздким, тогда вы должны посмотреть на Cells for Rails. драгоценный камень, который упрощает сборку инкапсулированных компонентов дисплея - комбинации логики контроллера и кода просмотра.
Спасибо за подробный ответ! Я бы предпочел не проверять роль пользователя в каждом отдельном виджете - это довольно избыточно и назойливо, когда у вас их десятки. Для моих взглядов и партитур я просто 'prepend_view_path '', если admin_signed_in?' - таким образом, я могу переопределить их на индивидуальной основе, если это необходимо, все, что мне не хватает, - это также элегантный метод для решения с помощниками. –
janfoeh
Если у вас есть десятки компонентов, я бы попытался найти то, что мог бы определить как базовый класс. Затем, в базовом классе, я бы сделал что-то вроде 'm =" admin _ # {method} "; return self.call (m), если admin_signed_in? && self.respond_to? (m) 'внутри него. Это похоже на то, что вы могли бы сделать с [ячейками] (https://github.com/apotonick/cells) красиво. –
Я дам эту идею вихрем, спасибо. Для этого проекта я уже взглянул на Cells и отклонил его по концептуальным причинам, но я дам ему еще один шаг. – janfoeh