Использование Rails 3, есть ли способ использовать вспомогательную команду link_to или любую вспомогательную функцию внутри модели?Просмотреть вспомогательную ссылку link_to в классе модели
ответ
Есть несколько причин, по которым вам может понадобиться link_to в модели. Да, @andy, это нарушение MVC, но это не значит, что вы должны получить очки за то, что не ответили на вопрос.
@schwabsauce, это проще, чем это. Первая строка даже не нужна, если вы делаете это в инициализаторе или что-то в этом роде. То же самое работает для .sanitize и .raw и цельной загрузки других потрясающих функций.
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
ActionController::Base.helpers.link_to(whatever)
Если вы хотите использовать autopaths вы, возможно, придется сделать это внутри link_to:
Rails.application.routes.url_helpers.page_path(@page)
Не без хакеров.
Если вы считаете, что вам нужна модель link_to
, вы, вероятно, нарушите какой-либо принцип Model-View-Controller architecture.
Модель должна быть местом для данных и бизнес-логики, но генерация ссылок почти наверняка является заданием для контроллера или представления (или Rails специально для вспомогательного класса).
Спасибо. Перемещено для просмотра помощника. Теперь все подходит. – Krule
Есть веские причины использовать помощников в моделях. Но более того, если вы собираетесь предложить мнение, по крайней мере, предложите решение, если они это продумают. Возможно, у кого-то с 2-мя повторителями голова прямо. –
Я получил эту работу со следующими включениями:
include ActionView::Helpers::UrlHelper
include ActionController::UrlFor
include Rails.application.routes.url_helpers
cattr_accessor :controller
def controller; self.class.controller; end
def request; controller.request; end
Тогда в моем контроллере я заселен атрибут (создание контроллера с нуля требует значительного объема данных в аргументах хэша).
Lead.controller = self
fwiw, Rails-документация действительно ведет к этому решению. Документы для ActionDispatch :: Routing :: UrlFor отмечают, что «Совет. Если вам нужно создавать URL-адреса с ваших моделей или в каком-либо другом месте, то ActionController :: UrlFor - это то, что вы ищете». Затем, когда вы включаете этот файл, он предлагает в качестве сообщения об ошибке: raise «Чтобы использовать #url_for, вы должны явно указать помощники маршрутизации». «Например,« include Rails.application.routes.url_helpers » Так что я думаю, что это приемлемо по соглашениям Rails - иногда это лучший способ/лучшее место для создания ссылки :) – schwabsauce
Да, например, если ваша модель обрабатывает авторизацию платежа стороннему внешнему шлюзу и должна генерировать URL-адрес возврата/отмены Вернуться к приложению. – hoffmanc
Будьте очень осторожны, следуя советам, изложенным в должности Чака, если вы делаете это в Rails 3.2. 1. Казалось бы, этот подход небезопасен, включая помощник link_to в классах без просмотра в Rails 3.2.1. Существует более безопасный способ (который работает для нас в любом случае), описанный ниже.
Когда мы использовали подход в сообщении Чак в одном из наших классов, он оказался очень тревожным и трудно отлаживающим. Это привело к возникновению побочных эффектов/ошибок, которые появились только в очень специфических (и редких) обстоятельствах.
Проблема, насколько мы можем сказать, что эта строка:
ActionView::Base.send(:include, Rails.application.routes.url_helpers)
говорит ActionView::Base
включить Rails.application.routes.url_helpers
, который ActionView::Base
, по-видимому, уже делает сама по себе. При этом он включает в себя url_helpers
второй раз, кажется, вызывает повторную инициализацию состояния маршрутов (@_routes в классах, в которые включен модуль ActionDispatch :: Routing :: UrlFor).
Это приводит к, казалось бы, случайный и необъяснимый «неопределенный метод„url_for“для ноля: NilClass» исключений в представлениях, которые пытаются вызвать, прямо или косвенно, метод url_for послеActionView::Base
включила url_helpers
во второй раз.
Решение, которое сработало для нас, было вместо того, чтобы сообщать ActionView::Base
, чтобы снова включить url_helpers
, просто включите модуль UrlHelper
, где бы он ни понадобился.
Затем, когда вам нужно использовать link_to и иметь доступ к пути, который вы можете просто сделать это (при условии, login_path действительна для вашего приложения):
include ActionView::Helpers::UrlHelper
...
link = link_to('here', Rails.application.routes.url_helpers.login_path)
Потребовалось очень много времени и довольно много от царапин на голове, чтобы отследить ошибки, вызванные двойным включением, и я просто хотел предупредить других о том, чтобы быть осторожными при настройке поведения базовых классов Rails.
Спасибо, что поделились этим! Я рад, что ты нашел лучший способ! –
One-liner: 'include ActionView :: Helpers :: UrlHelper' – karlingen
@karlingen - опуская ссылку на« Rails.application.routes ... »может привести к сообщению« аргументы, переданные в url_for, не могут быть обработаны. требуют маршрутов или предоставляют свою собственную реализацию " – Del
link_to хелперов, нарушение MVC
Что сказал Энди,
если вы генерации HTML в модели вы, вероятно, нужно сделать большой долго смотреть на то, что вы делаете и почему.
URL помощники
URL-адрес с другой стороны, часто приходят в удобных снаружи кода вида-контроллер, во всех видах услуг/виде/API/... классы, например, даже в моделях, если вам должен.
Да, Rails.application.routes.url_helpers представляет собой модуль, но это не означает, что вы просто должны включить его везде, где или забавный материал начнет происходит, как Гэри выразился:
https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all
Что вы можете сделать это:
delegate :url_helpers, :to => 'Rails.application.routes'
, а затем использовать, например
url_helpers.home_url
Этот вопрос был задан некоторое время назад, и в этот момент совет @ andy помог мне решить эту проблему. Однако вы правы в том смысле, что это не отвечает на реальный вопрос. – Krule