Как ссылаться на скомпилированные ресурсы из контроллера в Rails 3.1?

Я использую PDFkit в своем контроллере, чтобы создать серию PDF-файлов, заархивировать их и отправить пользователю.

Чтобы управлять стилями вывода, я сообщаю PDFKit, какие таблицы стилей использовать при создании контента. Мне нужно передать ссылку на файл файла CSS. Поскольку Rails теперь компилирует и переименовывает мои таблицы стилей, я не уверен, как ссылаться на скомпилированный ресурс CSS внутри моего контроллера.

Вот что я делал:

InvoicesController < ApplicationController
  def download
    kit = PDFKit.new(render_to_string(:show, :layout => false))
    kit.stylesheets << "#{Sass::Plugin.options[:css_location]}/application.css"
    kit.to_file("#{file_date_string}.pdf")
    # snip
  end
end

Sass::Plugin.options[:css_location] теперь возвращает неверное местоположение, не говоря уже о том, что application.css больше не является допустимым именем файла. Я должен упомянуть, что у меня есть файл app/assets/application.css, который служит манифестом для моих файлов SCSS, и он корректно работает в моих представлениях с помощью метода stylesheet_link_tag().

В основном то, что я ищу, - это контроллер, эквивалентный assets_path(), чтобы сделать что-то вроде этого:

kit = PDFKit.new(render_to_string(:show, :layout => false))
kit.stylesheets << asset_path('application.css')
kit.to_file("#{file_date_string}.pdf")

Кто-нибудь может помочь?


person cdreier    schedule 14.09.2011    source источник
comment
На самом деле здесь есть еще одна проблема: вам нужно использовать абсолютный путь к файловой системе для ссылки на таблицы стилей с pdfkit. Однако assets_path возвращает относительный веб-путь. На данный момент я решил проблему, создав pdf.css, который я поместил в public/stylesheets. Не идеально, поскольку он избегает конвейера ресурсов, но работает и заставляет меня отделять соответствующие стили PDF от моего app.css.   -  person Nico    schedule 14.09.2011
comment
Пожалуйста, укажите ответ как правильный. Это очень помогает сообществу.   -  person Bert Goethals    schedule 04.01.2012


Ответы (6)


Rails.application.assets плохо документирован, но он предоставляет доступ к хуку Rails в Sprockets как объекту Sprockets::Environment. Rails использует Sprockets для запуска всего конвейера ресурсов, и именно здесь вы должны подключиться к таким вещам, как это:

kit.stylesheets << Rails.application.assets['application.css'].pathname

https://github.com/sstephenson/sprockets говорит об этом:

Программный доступ к ресурсам

Вы можете использовать метод find_asset (псевдоним []) для извлечения актива из среды Sprockets. Передайте ему логический путь, и вы получите обратно экземпляр Sprockets::BundledAsset:

  environment['application.js']
  # => #<Sprockets::BundledAsset ...>

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

person Dave Burt    schedule 20.03.2012
comment
Похоже, он не работает с активами, требующими предварительной компиляции. Он просто загружает необработанный файл (в моем случае .scss). - person mbillard; 10.04.2012
comment
Я получаю обработанный вывод CSS обоими способами: irb(main):008:0* Rails.version => 3.2.2 irb(main):009:0> Rails.application.assets[main.css].to_s == Rails.application.assets[main.css.scss].to_s =› true - person Dave Burt; 27.04.2012
comment
Хотя содержимое файла совпадает, по какой-то причине я обнаружил, что оно неправильно отображается в PDF. Создание его с помощью промежуточного программного обеспечения стойки работает, но не путем явного создания экземпляра объекта PDFKit. Я обнаружил, что единственный способ заставить его работать - это поместить скомпилированную таблицу стилей в /public/, а затем закодировать эту таблицу стилей в соответствующий макет. например <link href="<%= "http://#{request.host}:#{request.port}/assets/pdf.css"%>" media="all" rel="stylesheet" type="text/css" /> - person benz001; 19.03.2013

view_context.asset_path 'application.css' должно помочь.

person Manuel Meurer    schedule 07.10.2011
comment
Если вы пытаетесь проверить в консоли Rails, ActionController::Base.new.view_context.asset_path "application.css" - person Jason Kim; 20.11.2012

Rails.application.assets['application.css'].pathname всегда возвращает исходный путь к необработанному ресурсу, а не к предварительно скомпилированному файлу, поэтому верхний ответ мне не помог.

Однако вызов to_s для связанного ресурса вместо pathname, по-видимому, правильно возвращает тело предварительно скомпилированного ресурса, поэтому вы можете просто использовать встроенный стиль вместо использования kit.stylesheets <<:

<style> <%= Rails.application.assets["application.css"].to_s %> </style>

person Louis Simoneau    schedule 10.11.2014

Одним из решений является встроенный CSS в ваше представление.

В HAML это может выглядеть так:

%style
  = Sass.compile(File.read(File.join(Rails.root, 'app', 'assets', 'stylesheets', 'sass', "application.scss")))

Или в ЕРБ:

<style>
  <%= Sass.compile(File.read(File.join(Rails.root, 'app', 'assets', 'stylesheets', 'sass', "application.scss"))) %>
</style>
person sbleon    schedule 14.09.2011

Лучший способ получить скомпилированное имя — из манифеста, который генерируется при компиляции.

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

Расположение манифеста по умолчанию:

File.join(Rails.public_path, config.assets.prefix, 'manifest.yml')

Но похоже, что вы можете получить к нему доступ как к хешу в config.assets.digests.

config.assets.digests[css_file_name_as_string]

person Richard Hulse    schedule 27.09.2011

Я думаю, что stylesheet_path("application") это то что ты ищешь

person RyanWilcox    schedule 14.09.2011
comment
К сожалению нет. stylesheet_path() — помощник представления, и мне нужно, чтобы он работал внутри действия контроллера. Я попытался включить модуль в контроллер, но он предполагает наличие метода assets_path, которого нет в области действия контроллера. - person cdreier; 14.09.2011