Rails资产管道中的动态CSS,即时编译

时间:2012-12-13 13:48:04

标签: ruby-on-rails ruby ruby-on-rails-3.2 less asset-pipeline

我正在使用Rails 3.2构建一个站点。自从我触及Rails或Ruby以来已经有3年了,所以我两个都生锈了,再加上我最后一次使用rails就是Rails 2.3。不用说,请原谅下面的任何“简单”问题。

以下是规格

  • Multi Tennant CMS /商店网站
  • 每个“商店”(也称为子域)可以通过CSS自定义具有自己的外观,感觉等
    • 可以在应用内的UI中执行自定义,允许用户更改Bootstrap的基本变量(例如@textColor@bodyBackground等)。
  • 我正在将less-rails-bootstrap gem用于Twitter Bootstrap外观等等。

以下是挑战

  1. 我需要能够将CSS的变量动态输出到一个混合到Bootstrap的文件中,以便拾取变量以创建最终的CSS
  2. 当用户更改CSS的变量时,现有样式基本上无效。我需要重新编译完整的CSS并将其写回磁盘,内存流或其他一些我可以抓住它的位置(请记住这是使用less
  3. 我需要不同的CSS来吐出每个子域。关于如何处理此问题的任何建议?
  4. 使问题进一步复杂化......

    ...鉴于我基本上必须找到一些方法来动态编译CSS,这意味着我必须包含我通常不会在生产环境中使用的GEMS。表现非常重要。有没有办法隔离这个?一旦CSS被无效并重新生成,我就可以获取内容并将其写入磁盘或存储在某些memcached / redis / etc中。表现的实例。

    任何评论,即使只是为了指出我的总体方向,我们将不胜感激。

    谢谢!

1 个答案:

答案 0 :(得分:3)

这是我最终落实的解决方案:

  • 我最终切换到bootstrap-sass而不是https://github.com/thomas-mcdonald/bootstrap-sass
  • 对我的application.rb文件进行了以下更改,以确保在环境中始终包含:asset组:

    if defined?(Bundler)
        # If you precompile assets before deploying to production, use this line
        # Bundler.require(*Rails.groups(:assets => %w(development test)))
        # If you want your assets lazily compiled in production, use this line
        Bundler.require(:default, :assets, Rails.env)
    end
    
  • 使用了http://www.krautcomputing.com/blog/2012/03/27/how-to-compile-custom-sass-stylesheets-dynamically-during-runtime/发现的Kraut Computing的Manuel Meure(谢谢Manuel!)提供的概念。

    • 我做了一些调整以适应我自己的需要,但Manuel所说明的核心概念是我编译过程的基础。
  • 在我的模型中(我们称之为“网站”),我有一段代码如下:

    # .../app/models/site.rb
    ...
    
    BASE_STYLE = "
      @import \"compass/css3\";
    
      <ADDITIONAL_STYLES>
    
      @import \"bootstrap\";
      @import \"bootstrap-responsive\";
    ".freeze
    
    # Provides the SASS/CSS content that would 
    # be included into your base SASS content before compilation
    def sass_content
      "
      $bodyBackground: #{self.body_background};
      $textColor: #{self.text_color};
      " + self.css # Any additional CSS/SASS you would want to add
    end
    
    def compile_css(test_only = false, force_recompile = false)
    
      # SassCompiler is a modification of the information made available at the Kraut Computing link
      compiler = SassCompiler.new("#{self.id}/site.css", {:syntax => :scss, :output_dir => Rails.root.join('app', 'assets', 'sites')})
    
      # Bail if we're already compiled and we're not forcing recompile
      return if compiler.compiled? && !force_recompile && !test_only
    
      # The block here yields the content that will be rendered
      compiler.compile(test_only) {
        # take our base styles, slap in there some vars that we make available to be customized by the user
        # and then finally add in our css/scss that the user updated... concat those and use it as
        # our raw sass to compile
        BASE_STYLE.gsub(/<ADDITIONAL_STYLES>/, self.sass_content)
      }
    end
    

我希望这会有所帮助。我知道它偏离了原来的帖子,但是它的偏离是因为这似乎是解决问题最容易解决的问题。

如果我没有回答您的具体问题,请随时发表评论,以便我尽可能扩大。

谢谢!