Я изучал "рекомендуемый" способ использования помощников вида Rails (например, link_to
, content_tag
) в обычном классе ruby, например, для презентатора. Кажется, на этом фронте очень мало информации, и я хотел получить представление о том, что думает сообщество Stack.
Итак, у нас есть варианты. (Заметьте, я использую Rails 4 и меньше беспокоюсь о более старых версиях)
Включить необходимые модули вручную
Это, пожалуй, самый чистый способ, поскольку включены только необходимые помощники. Однако я обнаружил, что этот метод не работает в некоторых случаях, поскольку обычный контекст представления, предоставляемый в простых помощниках Rails, настроен для текущего запроса. url_for
не будет знать о текущем запросе, например, хост может не совпадать.
class MyPresenter
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::CaptureHelper
def wrapped_link
content_tag :div, link_to('My link', root_url)
end
end
Использовать ActionController::Base.helpers
Так как Rails 3, ActionController::Base
включил метод helpers
для доступа к текущему контексту представления. Я считаю, что контекст представления, предоставляемый этим методом, настроен так, как это было бы в помощнике rails, но я мог ошибаться. Там нет никакой документации об этом, которая кажется тревожной, но на практике она работает довольно хорошо.
class MyPresenter
def wrapped_link
h.content_tag :div, h.link_to('My link', h.root_url)
end
protected
def h
ActionController::Base.helpers
end
end
Я считаю, что этот контекст представления также можно смешивать с include
, но у рельсов видят, что помощники имеют сотни методов, и он чувствует себя грязным, чтобы включить их все без разбора.
Ввод контекста представления при вызове ведущего
Наконец, мы могли бы просто передать контекст представления классу при его инициализации (или, альтернативно, методом render
)
class MyPresenter
attr_accessor :context
alias_method :h, :context
def initialize(context)
@context = context
end
def wrapped_link
h.content_tag :div, h.link_to('My link', h.root_url)
end
end
class MyController < ApplicationController
def show
# WARNING - `view_context` in a controller creates an object
@presenter = MyPresenter.new(view_context)
end
end
Лично я склоняюсь к двум последним вариантам, но без окончательного ответа команды Rails (которую я смог найти) я чувствовал себя немного неуверенным. Кто лучше спросить, чем Stack!