// Variables $font-size: 12px; // Nested rules #foo { .bar { font-size: $font-size; } } // Include other Sass style sheets @import 'bar'; // Mixins @mixin has-cats { &::before { content: 'meow'; display: block; } } #internet { @include has-cats; }
// _my-ui.scss #foo { background: nth($palette, 1); color: nth($palette, 2); }
// palette1.scss $palette: (red green); @import 'my-ui';
// palette2.scss $palette: (blue yellow); @import 'my-ui';
// dynamic-palette.scss $palette: get-dynamic-palette(); @import 'my-ui';
# config/initializers/sass.rb module Sass::Script::Functions def get_dynamic_palette palette = 2.times.map do color = '#%06x' % (rand * 0xffffff) Sass::Script::Value::Color.from_hex(color) end Sass::Script::Value::List.new(palette, :space) end end
// app/assets/stylesheets/dynamic-palette-rails.css.scss $palette: get-dynamic-palette-from-user-somehow-magically(); @import 'my-ui';
# sass-rails/lib/sass/rails/template.rb module Sass module Rails class SassTemplate < Tilt::Template # ... def evaluate(context, locals, &block) cache_store = CacheStore.new(context.environment) options = { :filename => eval_file, :line => line, :syntax => syntax, :cache_store => cache_store, :importer => importer_class.new(context.pathname.to_s), :load_paths => context.environment.paths.map { |path| importer_class.new(path.to_s) }, :sprockets => { :context => context, :environment => context.environment } } sass_config = context.sass_config.merge(options) engine = ::Sass::Engine.new(data, sass_config) css = engine.render engine.dependencies.map do |dependency| context.depend_on(dependency.options[:filename]) end css rescue ::Sass::SyntaxError => e context.__LINE__ = e.sass_backtrace.first[:line] raise e end # ... end end end
# lib/sass_custom_palette.rb class SassCustomPalette TEMPLATE = <<-EOS.freeze $palette: get-custom-palette(); @import 'my-ui'; EOS def initialize(color) @color = color end def render Sass::Engine.new(TEMPLATE, sass_custom_options).render end private def sass_custom_options { syntax: :scss, style: :expanded, custom: { color: @color } } end end
# config/initializers/sass.rb module Sass::Script::Functions def get_custom_palette color = Sass::Script::Value::Color.from_hex( options[:custom][:color] ) factor = Sass::Script::Value::Number.new(20, '%') palette = [ lighten(color, factor), darken(color, factor) ] Sass::Script::Value::List.new(palette, :space) end end
# app/controllers/palettes_controller.rb class PalettesController < ApplicationController def custom_palette custom_renderer = SassCustomPalette.new( params[:custom_color] ) @css = custom_renderer.render end end
-# app/views/palettes/custom_palette.css.haml = @css.html_safe
Sass::SyntaxError - File to import not found or unreadable: my-ui.
class SassCustomPalette private def load_paths root = Rails.root.join('app', 'assets', 'stylesheets') Dir[root.join('includes')] end def sass_custom_options { syntax: :scss, style: :expanded, load_paths: load_paths, custom: { color: @color } } end end
// app/assets/stylesheets/includes/_my-ui.scss #foo { background: nth($palette, 1); color: nth($palette, 2); }
[memcached.org](http://memcached.org) / [github.com/mperham/dalli](https://github.com/mperham/dalli)
# config/environments/production.rb config.cache_store = :mem_cache_store, \ MEM_CACHE_SERVER, MEM_CACHE_OPTIONS
Rails.cache.write('foo', 'bar') Rails.cache.fetch('foo') #=> 'bar'
class SassRenderer def initialize(template, cache_key, options) @cache_key = cache_key @engine = Sass::Engine.new(template, options) end def render from_cache { @engine.render } end def cached? Rails.cache.exist?(@cache_key) end def get_cached_css Rails.cache.fetch(@cache_key) end private def set_cached_css(css) Rails.cache.write(@cache_key, css) end def from_cache(&write_block) get_cached_css || write_block.call.tap { |css| set_cached_css(css) } end end
class SassCustomPalette def initialize(color) @color = color @cache_key = "custom_palette/#{@color}" @engine = SassRenderer.new( TEMPLATE, @cache_key, sass_custom_options ) end delegate :render, to: :@engine end
# app/workers/sass_custom_palette_worker.rb class SassCustomPaletteWorker include Sidekiq::Worker def perform(color) SassCustomPalette.new(color).render end end
class SassCustomPalette def render_async unless @engine.cached? SassCustomPaletteWorker.peform_async(@color) end @cache_key end end
class SassRenderer def self.get_by_key(key) Rails.cache.fetch(key) end def self.cached?(key) Rails.cache.exist?(key) end private def get_cached_css self.class.get_by_key(@cache_key) end end
class PalettesController < ApplicationController def request_custom_palette custom_renderer = SassCustomPalette.new( params[:custom_color] ) @key = custom_renderer.render_async end def check_custom_palette @ready = SassRenderer.cached?(params[:key]) end def custom_palette @css = SassRenderer.get_by_key(params[:key]) end end
@elpapapollo jeremy@pushagency.io github.com/jfairbank