Can Ruby hashes be included in Sass and CoffeeScript, allowing data to be shared?

549 views Asked by At

I am wondering if a ruby hash can be shared between Sass and CoffeeScript with a minimum of fuss.

I've looked around for an answer to this but found nothing conclusive. Sources, such as the documentation for Sass, talk about how to link files of the same type and how to manipulate data structures within the language, but don't touch on whether data can be imported from elsewhere, or whether ruby code can be interpreted in someway - the only similar thing I can think of is compass using a .rb file for it's config.

My instinct suggests this is (or should) be possible, both languages are Ruby-like and capable of interpreting hashes.

As this is a practical problem I've faced several times (DRYing up pre-processed front end code, but also providing the same values for back-end processing, such as generating an SVG in an HTML template) but never solved in a really clean way I would accept a solution that involved using Rails.

Please note, I am quite specific about this relating to the pre-compilation stage of front end asset production, namely Sass and CoffeeScript. Answers which involve CSS, JavaScript or require a browser are not what I'm looking for.

Extra bits

I've decided to add an example, here are three definitions of the same data as key value pairs:

Ruby

colours = { brandBackground: '#f00', brandForeground: '#00f', brandText: '#0f0' }
colours[:brandBackground]

Sass Map

$colours: ( brandBackground: '#f00', brandForeground: '#00f', brandText: '#0f0' )
map-get($colours, brandBackground)

CoffeeScript

colours = { brandBackground: '#f00', brandForeground: '#00f', brandText: '#0f0' }
colours.brandBackground

Coffeescript and Ruby hash definitions are identical, Sass is very close ... if this can work then colours (or any other variable) could be defined in one place then used throughout the front and back end by any code.

2

There are 2 answers

5
hedgesky On BEST ANSWER

You can turn your CoffeeScript and SASS into ERB templates which will be preprocessed (and thus you can use all awesome Ruby's possibilities in them). There is a little post that describes this: https://robots.thoughtbot.com/dont-repeat-your-ruby-constants-in-javascript.

Update

Add this code into lib/shared_assets_data.rb:

module SharedAssetsData
  def self.colors_hash
    { brandBackground: '#f00', brandForeground: '#00f', brandText: '#0f0' }
  end

  def self.sassify(hash)
    hash.map do |key, value|
      "#{key}: '#{value}'"
    end.join(', ').prepend('( ').concat(' )')
  end

  def self.coffefy(hash)
    hash.map do |key, value|
      "#{key}: '#{value}'"
    end.join(', ').prepend('{ ').concat(' }')
  end
end

Then to enable autoloading lib directory add this line to config/application.rb:

config.autoload_paths += %W(#{Rails.root}/lib)

After that you can do following:

# screen.sass.erb
$colours: <%= SharedAssetsData.sassify(SharedAssetsData.colors_hash) %>
body
  background: map-get($colours, brandBackground)

# screen.coffee.erb
colours = <%= SharedAssetsData.coffefy(SharedAssetsData.colors_hash) %>
console.log colours.brandBackground
8
Chase On

I think your best bet is to use gon. Gon is a gem that allows you to pass ruby variables to javascript/coffeescript. From there you can inline a style that makes use of the ruby hash.

Sass/CSS are really only about styles, and while Sass can have variables and do math, you shouldn't use it as a store for more complex data structures, this will make you code very difficult to maintain. Data storage and transport just isn't the job of Sass.

So, as for gon. Try something like this in your controller:

gon.ruby_hash = {key: value}

now in you coffeescript:

gon.ruby_hash

You'll be able to access the hash by calling gon.ruby_variable_name.