web-dev-qa-db-ja.com

Railsアセットパイプラインを使用するときにCSSをインライン化する方法

Railsのstylesheet_link_tagヘルパーメソッドを使用してビューに追加できるcssの取得元のリンクを含むスタイルタグをページに含める代わりに、cssをページ内に直接インライン化する必要があります。

これは私がこれまでに思いついたものです:

%style(type="text/css")=File.read(physical_asset_path("email.css"))

しかし、アセットの物理パスを提供するRailsのヘルパーメソッドが見つかりません。physical_asset_pathは私が発明したダミーのメソッドです。

Rails 3.2.xを使用するときに、アセットの物理パスを取得する方法を知っている人はいますか?

コモンRailsアセットパス内のcssファイルから-インラインでスタイルシートを取得するためのより簡単でより良い方法はありますか?

使用例:ほとんどの電子メールクライアントは、ユーザーの確認なしに外部ソース(css、画像など)にアクセスしません。したがって、電子メールを適切に表示するには、電子メールのHTML内にCSSを埋め込む必要があります。

24
gucki

Premailerまたはpremailer-Rails3を使用

https://github.com/fphilipe/premailer-Rails または https://github.com/alexdunae/premailer

ジョーのオタクパーティーは言う:

また、Premailer gemを使用して、リンクされたスタイルシートを電子メールビューに自動的にインライン化しました。メールのレイアウトは次のようになります。

%html
  %head
    = stylesheet_link_tag 'email'

    %style{:type => "text/css"}
      :sass
        @media all and (max-width: 480px)
          table#container
            width: auto !important
            max-width: 600px !important
         ... and so on for the mobile code

    %body 
      Email body here.
      %table
        Lots of tables.

HTMLにスタイルシートを含めます。 Premailerはそれをダウンロードして処理し、cssルールをHTMLにインラインで挿入します。

Premailerはまだ別のcssファイルにあるルールを処理できないため、@ mediaルールはメールレイアウトでインラインにする必要があります。

Premailer-Rails3を使用してPremailerをRails 3.残念ながら、premailerとpremailer-Rails3に多数のバグが見つかりました。プロジェクトのフォークは https:/ /github.com/joevandyk/premailer および https://github.com/joevandyk/premailer-Rails 。フォークはいくつかのエンコーディングのバグを修正し、premailerによって行われたいくつかの奇妙なcss処理を削除します- Rails3では、プリメーラーがメールレイアウトに埋め込まれたルールを取り除かないようにできます。

また、sass-Railsにバグがあり、インラインsassコードにimage-urlを埋め込むことができません。 https://github.com/Rails/sass-Rails/issues/71 Premailer-Rails3は、電子メールが生成されるだけでなく、実際に配信されるときにActionMailerにフックします。を参照してください。テストを実行する場合、メールは実際には送信されないため、テスト中にpremailer-Rails3フックは実行されません。テスト中にプリメーラー処理を実行できるかどうかを確認するために時間を費やしたことはありませんが、それは良いことです。

また、premailer-Rails3でのフォークは、プリメーラーが出て実際にリンクされたCSSファイルをダウンロードすることを想定しています。 Rails 3.1アセットパイプラインを使用して、処理されたcssをダウンロードせずに取得できるはずです。メールの見栄えを良くするという非常に厄介な仕事をしてくれたJordanIsipに特に感謝します。 CSS/HTMLを書くのは面白くありませんでした。

更新:

Roadie の方が良いオプションのようです。指摘してくれたSeth Broに感謝します。

16

Rails.application.assets.find_asset('email').to_sは、コンパイルされたアセットを文字列として返します。

60
Seth Bro

(申し訳ありませんが、この回答はhtmlではなくHAMLにありますが、HAMLファンにとっては問題にはなりません)

この質問は、HTMLメールテンプレートを作成するためにSassとしてコンパイルされたcsshtmlにインライン化する方法を探しているときに見つけました。

上記のアドバイスを組み合わせて、headページのhtmlで次のコードを使用しました。

<style type="text/css">
  <%= Rails.application.assets['path/to/sass/file'].to_s.html_safe %>
</style>

このコードはSassCSSとしてコンパイルし、CSSを<style>タグに挿入します。 html_safeは、cssで使用されている引用符('および")または山括弧(>および<)がエスケープされないようにします。

path/to/sass/fileは、スタイルシートリンクタグを作成するときに使用するものと同じです。

<%= stylesheet_link_tag 'path/to/sass/file', :media => 'all' %>
9
Beau Smith

_Rails.application.assets['asset.js']_は、ローカル環境でのみ機能します。Railsアセットのコンパイルは、本番環境とステージング環境の両方で無効になっているためです。

Railsアセットパイプラインを使用する場合は、cssをインライン化するためにRails.application.assets_manifest.find_sources('asset.js').first.to_s.html_safeを使用する必要があります。

6
ThisIzKp

SethBroの回答にコメントを追加できません。 #[] の代わりに #find_assetRails.application.assets["email"].to_s

再「資産は圧縮されません」。それは真実ではない。コンプレッサーを有効にしている場合は圧縮されます(Rails config):

Rails.application.configure do
  # ...
  config.assets.css_compressor = :sass
  config.assets.js_compressor  = :uglify
end

デフォルトでは、これは実稼働環境で有効になっていることに注意してください(config/environments/production.rb)。

4
ixti

Railsのグーグルアンプ互換ページで使用するためにcssをインライン化しようとしていました。 vyachkonovalov から次のヘルパーを見つけました。これは、本番環境とローカルで作業している私にとって唯一のものでした。

以下をerbテンプレートに追加します。

<style amp-custom>
  <%= asset_to_string('application.css').html_safe %>
</style>

そして、ApplicationHelperへのヘルパー。ローカルおよび本番環境で完全に機能します。

module ApplicationHelper
  def asset_to_string(name)
    app = Rails.application
    if Rails.configuration.assets.compile
      app.assets.find_asset(name).to_s
    else
      controller.view_context.render(file: File.join('public/assets', app.assets_manifest.assets[name]))
    end
  end
3
svnm

同じ問題がありましたが、Premailerの同様の問題に対して @ phlegxの回答 を使用して解決しました。

環境に安全なソリューションを使用するには、

(Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)).find_asset('email.css').to_s

私はそれを私のアプリのヘルパーにパッケージ化しました:

# app/helpers/application_helper.rb
# Returns the contents of the compiled asset (CSS, JS, etc) or an empty string
def asset_body(name)
   (Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)).find_asset(name).to_s
end
2
Goulven

tl; dr(Roadieなし):

%style(type="text/css")
  = render template: '../assets/stylesheets/email_responsive.css'

実際にCSSをインラインスタイルとして適用する場合、 roadie-Rails をお勧めします(これは、Rails Roadie のラッパーです)。また、 hrefs、srcsなどの絶対化などの他の優れた機能。

インライン(email.scss)スタイルシートと非インライン(email_responsive.css)スタイルシートの両方を組み合わせた使用法。どちらもapp/assets/stylesheetsにあります。

-# This will be inlined and applied to HTML elements.
-# Note that you need to include this in your asset config, e.g.:
-# Rails.application.config.assets.precompile += %w(... email.css)
-# (You need to list it as `email.css` even if it's actually `email.scss`.)

= stylesheet_link_tag 'email'


-# E.g. for media queries which can't be inlined - yeah, some iOS devices support them.
-# This will not be inlined and will be included as is (thanks to `data-roadie-ignore`).
-# `template:` marks it as a full template rather than a partial and disables `_` prefix.
-# We need to add the extension (`.css`) since it's non-standard for a view.

%style(type="text/css" data-roadie-ignore)
  = render template: '../assets/stylesheets/email_responsive.css'
1
Halil Özgür

あなたはこれを使うことができます:

Rails.root.join('public', ActionController::Base.helpers.asset_path("email.css")[1..-1]).read.html_safe