Динамический CSS в конвейере ресурсов Rails, компилируется на лету

Я строю сайт в Rails 3.2. Прошло 3 года с тех пор, как я коснулся Rails или Ruby, так что я ржавый на обоих, плюс последний раз, когда я использовал rails, это был Rails 2.3. Излишне говорить, пожалуйста, извините за любые "простые" вопросы ниже.

Вот технические характеристики

  • Мульти Теннант CMS/ Сайт магазина
  • Каждый "Магазин" (он же субдомен) может иметь свой собственный внешний вид, стиль и т. Д. С помощью настроек CSS
    • Настройки могут быть выполнены в пользовательском интерфейсе приложения, что позволяет пользователю изменять основные переменные Bootstrap (т.е. @textColor, @bodyBackground, так далее.)
  • Я использую less-rails-bootstrap жемчужина в Twitter Bootstrap, внешний вид и т.д.

Вот проблемы

  1. Мне нужно иметь возможность динамически выводить переменные для CSS в файл, который смешивается с Bootstrap, поэтому переменные подбираются для создания окончательного CSS
  2. Когда пользователь изменяет переменную для CSS, существующий стиль в основном становится недействительным. Мне нужен полный CSS, перекомпилированный и записанный обратно на диск, в поток памяти или в другое место, где я могу получить его (помните, что это использует less)
  3. Мне нужен другой CSS, чтобы выплевывать на поддомен. Любые предложения о том, как подойти к этому?

Дальнейшее усложнение вопроса...

... учитывая, что мне, по сути, придется найти какой-то способ компиляции CSS на лету, это означает, что я должен включить GEMS, чего обычно не было бы в производственной среде. Производительность будет очень важна. Есть ли способ изолировать это? После того, как CSS был признан недействительным и восстановлен, я мог взять содержимое и либо записать его на диск, либо сохранить в каком-нибудь memcached / redis / etc. экземпляр для исполнения.

Любые комментарии, даже если просто указать мне в общем направлении будут оценены.

Спасибо!

1 ответ

Решение

Вот решение, которое я наконец-то нашел:

  • Я перешел на 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
    
  • Использованы концепции, предоставленные Мануэлем Меером (спасибо, Мануэль!) Из Kraut Computing, который можно найти по адресу http://www.krautcomputing.com/blog/2012/03/27/how-to-compile-custom-sass-stylesheets-dynamically-during-runtime/.

    • Я внес некоторые коррективы в соответствии со своими потребностями, но основные концепции, проиллюстрированные Мануэлем, стали основой для моего процесса компиляции.
  • В моей модели (назовем это "Сайт") у меня есть фрагмент кода, который выглядит следующим образом:

    # .../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
    

Надеюсь, это поможет. Я знаю, что это отклонение от первоначального поста, но оно отклонилось, потому что это казалось наиболее достижимым решением проблемы.

Если я не ответил на конкретный вопрос, который у вас есть, не стесняйтесь комментировать, чтобы я мог расширить, где это возможно.

Спасибо!

Другие вопросы по тегам