如何在使用rails资产管道时内联css

时间:2012-04-30 16:15:49

标签: ruby-on-rails asset-pipeline

我没有让页面包含带有链接的样式标记,而是使用rails'stylesheet_link_tag辅助方法将其添加到我的视图中,我希望将css内联直接放在页。

这是我到目前为止所提出的:

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

但我找不到任何rails的帮助方法,它给了我资产的物理路径 - physical_asset_path只是我发明的虚拟方法。

有人知道在使用rails 3.2.x时如何获取资产的物理路径?

是否有更简单/更好的方式来获取样式表 - 来自公共铁路资产路径中的css文件 - 内联?

使用案例:大多数电子邮件客户端在没有用户确认的情况下不访问外部源(如css,图像)。因此,要正确显示电子邮件,我需要将CSS嵌入电子邮件的HTML中。

9 个答案:

答案 0 :(得分:59)

Rails.application.assets.find_asset('email').to_s会将编译后的资产作为字符串返回。

答案 1 :(得分:16)

使用预制商或premailer-rails3

https://github.com/fphilipe/premailer-rails3 要么 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中包含样式表。预编译器下载它,进程   它,并在HTML中内嵌插入css规则。

     

@media规则需要在电子邮件布局中内联,因为   预编译者无法处理那些在单独的css文件中的文件。

     

我们使用premailer-rails3将Premailer集成到Rails 3中。   不幸的是,我们在预编译器中发现了一堆错误   premailer-Rails3中。我们的项目分支在   https://github.com/joevandyk/premailer和   https://github.com/joevandyk/premailer-rails3。叉子修好了一些   编码错误,删除一些奇怪的css处理的东西   premailer-rails3,允许预制器不剥离嵌入式   电子邮件布局中的规则以及其他一些内容。

     

我们还在sass-rails中发现了一个错误,你无法在其中嵌入image-urls   内联sass代码。见https://github.com/rails/sass-rails/issues/71   当电子邮件实际存在时,Premailer-rails3挂钩到ActionMailer   交付,而不仅仅是生成。运行测试时,电子邮件不是   实际发送,所以premailer-rails3挂钩不会在运行期间   试验。我没有花时间看看是否有可能获得   预测程序处理在测试期间运行,但这将是一个很好的   要做的事。

     

另外,我们在premailer-rails3上的forc假设你想要预编译器   出去实际下载链接的CSS文件。它应该是   可以使用Rails 3.1资产管道来获取已处理的css   没有下载它。非常特别感谢Jordan Isip   做了超级烦人的工作,确保电子邮件看起来很棒   那里的不同客户。写那个CSS / HTML看起来不像   乐趣。

<强>更新

Roadie似乎是更好的选择。感谢Seth Bro指出它。

答案 2 :(得分:8)

(抱歉,此答案位于html,而不是HAML ......但对于HAML粉丝而言,这不应该是一个问题

我在寻找将Sass编译为css时将html内联到head以创建HTML电子邮件模板的方法时发现了这个问题。

结合上述建议,我在html页面的<style type="text/css"> <%= Rails.application.assets['path/to/sass/file'].to_s.html_safe %> </style> 中使用了以下代码:

Sass

此代码将CSS编译为<style>,然后将css插入html_safe标记。 '确保css中使用的任何引号(">)或尖括号(<path/to/sass/file)都不会被转义。

<%= stylesheet_link_tag 'path/to/sass/file', :media => 'all' %> 与创建样式表链接标记时使用的相同:

$ rails s
=> Booting Puma
=> Rails 5.0.0.beta2 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
DEPRECATION WARNING: before_filter is deprecated and will be removed in Rails 5.1. Use before_action instead. (called from block in tsort_each at /Users/ericcarpentier/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/tsort.rb:226)
DEPRECATION WARNING: after_filter is deprecated and will be removed in Rails 5.1. Use after_action instead. (called from block in tsort_each at /Users/ericcarpentier/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/tsort.rb:226)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in tsort_each at /Users/ericcarpentier/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/tsort.rb:226)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in tsort_each at /Users/ericcarpentier/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/tsort.rb:226)
Exiting
/Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/activesupport-5.0.0.beta2/lib/active_support/logger_silence.rb:23:in `level': undefined method `[]' for nil:NilClass (NoMethodError)
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/server.rb:140:in `log_to_stdout'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/server.rb:76:in `start'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/commands_tasks.rb:90:in `block in server'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/commands_tasks.rb:85:in `tap'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/commands_tasks.rb:85:in `server'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/command.rb:20:in /`run'
  from /Users/ericcarpentier/.rvm/gems/ruby-2.2.2/gems/railties-5.0.0.beta2/lib/rails/commands.rb:19:in `<top (required)>'
  from bin/rails:9:in `require'
  from bin/rails:9:in `<main>'

答案 3 :(得分:5)

Rails.application.assets['asset.js']仅适用于本地环境,因为在生产和登台环境中都禁用了rails资产编译。

使用rails资产管道时,

Rails.application.assets_manifest.find_sources('asset.js').first.to_s.html_safe应该用于内联css。

答案 4 :(得分:4)

无法在Seth Bro的回答中添加评论。最好使用#[]代替#find_assetRails.application.assets["email"].to_s

重新“资产不会被压缩”。这不是真的。如果您启用了压缩器(在rails配置中),它将被压缩:

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

请注意,默认情况下,这是在生产环境(config/environments/production.rb)中启用的。

答案 5 :(得分:2)

我试图将内嵌css用于带有rails的google amp兼容页面。我从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

答案 6 :(得分:1)

tl; dr(没有Roadie):

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

对于实际应用CSS作为内联样式,我建议roadie-rails(这是Roadie的Rails包装器)。它还有其他简洁的功能,如绝对值href s,src等。

结合内联(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'

答案 7 :(得分:0)

您可以使用此:

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

答案 8 :(得分:0)

遇到相同的问题,使用@phlegx's answer解决了与Premailer中类似的问题。

对于环境安全的解决方案,您需要使用

(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