Rails asset pipeline-как включить актив не в путь к активу?


Итак, я преобразовал это мое приложение с несколькими оболочками, чтобы использовать конвейер активов, представленный в Rails 3.1. По большей части это было удивительно легко, и я влюблен в возможность предварительной обработки, которая позволяет использовать встроенный Ruby в ваших CSS/JS файлах. Однако я столкнулся с серьезной проблемой, которую, несмотря на мощь звездочек, трудно решить. Мое приложение может быть запущено с любым количеством скинов (или, скорее," идентичностей"), которые выбираются во время выполнения. Этот параметр" идентичность" настраивает такие вещи, как каталог кэша, подключение к базе данных, пути просмотра - и действительно пути активов. В то время как все "идентичности" могут иметь свою собственную таблицу стилей, существует также общая, которая используется во всех экземплярах. Таким образом, структура папок assets выглядит примерно так:

In / app / assets/stylesheets / aplication.CSS.erb:

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>

Это загружает две таблицы стилей, и критически важно, что он использует настроенные пути активов для их разрешения (вот почему я использую require_assets вместо стандартного require и include директивы, так как они не попадают в решатель). Он возвращает первые найденные совпадения и позволяет мне очень легко переопределить часть или весь стиль по умолчанию. Итак

/app/assets/stylesheets/shared.css

Можно переопределить, поместив файл с тем же именем в папку ресурсов экземпляра

/app/assets/[identity]/stylesheets/shared.css

И если такой файл не существует, он автоматически возвращается к общему файлу по умолчанию.CSS.

Все это работает блестяще - я использую ту же технику для Javascripts, изображений и шрифтов, и все становится аккуратно обрабатывается и упаковывается во время предварительной компиляции. НО. Существует тип (бокового) наследования, которого я не могу достичь; иногда кожа для идентичности настолько похожа на другую, что различаются только несколько линий dosen (например, идентичная компоновка, но с другой цветовой схемой), и я действительно хочу иметь возможность сделать что-то вроде этого:

Активы / таблицы стилей / приложения.CSS.erb:

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>

Assets / current_identity/stylesheets / overrides.css:

<% require_asset("../../some_other_identity/stylesheets/overrides.css") %>
/* followed by the dosen or so lines that differ for this skin */
...

Это Не удается, потому что в текущем контексте "some_other_identity" не находится в пути к активу - Rails не находит файл в режиме dev, и, конечно, он не включается во время предварительной компиляции. И если я включаю его в путь активов, он загружает неправильные переопределения.css (может быть только один). Так что я экспериментировал с тем, чтобы поместить что-то вроде этого в верхней части переопределений.css:

<%= File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css")) %>
/* rest of CSS */
...

И действительно, это работает так, как и ожидалось. НО. Потому что теперь я использую активы конвейер для обслуживания всех активов я больше не могу ссылаться на изображения в CSS с фиксированным путем - я должен использовать <%= asset_path("some_image.png") %>, чтобы распознаватель путей мог работать по своей магии. Это означает, что мой overrides.css на самом деле overrides.css.erb, и, конечно, предварительная обработка ERB не происходит, когда вы делаете File.read(). Итак, я застрял! Помогите! Кто-нибудь?

Редактировать: Если я использую

<%= ERB.new(File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb"))).result %>

Он пытается разобрать ERB, но я получаю

undefined method `asset_path' for main:Object

Что, конечно, связано с тем, что я использую asset_path("some_image.png") etc в файле, который я пытаюсь включать.

1 6

1 ответ:

Хорошо, после нескольких часов поиска я наткнулся на список доступных вспомогательных методов в Sprockets - это сэкономило бы мне много времени, если бы это было связано с man-страницей Sprockets на GitHub (есть ссылка, но она указывает на #FIXME). Из документов API Sprockets:

  • (Object) evaluate(path, options = {})
  • читает path и запускает процессоры в файле.
  • это позволяет захватить результат актива и включить его непосредственно в другой.
  • <%= evaluate "bar.js" %>

Бинго! Я изменил свою директиву include на:

<%= evaluate(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb")) %>

И CSS обрабатывается и результаты вставляются, именно так, как я хотел, чтобы это работало.