Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Asset Pipeline With Themes

I have an application that allows users to choose a theme for their page. There are several different themes for them to choose from.

The HTML structure to each of the pages is exactly the same with the same class names on divs. The CSS varies to fill out the theme. When the user chooses a theme, I store the theme id in the database and query for it when the page is accessed, loading the appropriate CSS file in the of application_layout.html.erb:

<%= yield(:theme_style) %>

On users_page.html.erb, I grab the appropriate file with:

<%= provide(:theme_style, "theme_styles/#{@user.style.style_filename_file_name}") %>

Because the page structure doesn't change, it is important that the CSS files aren't compiled together in one big CSS file or else the last theme will be the only one available because it will overwrite all previous styles. How can I get Rails to handle the theme files?

In production.rb, I have config.assets.precompile += ['theme_styles/basic.css', 'theme_styles/two-column.css'] but that doesn't seem to do the trick as it tells me that it is not precompiled.

I can't seem to find enough information anywhere to put me in the right direction and I've looked over blogs, SO questions and the Rails documentation.

like image 239
unlikely_monkey Avatar asked Oct 02 '12 04:10

unlikely_monkey


1 Answers

I know this is an old one, but I figured I would answer with what I did in case it helps anyone else. I had a similar need in my app and after not finding a lot of results, and running into an IE maximum number of selector bug when using them in one css file controlled by custom selectors I ended up going the route of having each themes in different CSS files by creating a folder structure that looks like this:

overall folder structure:

  • /app/assets/stylesheets/
  • /app/assets/stylesheets/all/
  • /app/assets/stylesheets/theme-1/
  • /app/assets/stylesheets/theme-2/
  • etc.

in app/assets/styleshseets I put application.css.scss (or just css if you aren't using sass) this file has a require self and some mixins I use on all sites but that's it

 *= require_self

Going forward I have a css folder for each theme and a folder for all, with a manifest for each (manifests go in the main /stylesheets folder). It ends up being a little work to get setup right, but works like a charm once configured, no more overlapping or extraneous css served to someone with a different theme, solves IE maximum selectors issues too.

more details

all folder for all shared css

/app/assets/stylesheets/all/

so put any css files you are using on all themes in there. I put my bootstrap for a project in there, but you can put any shared CSS in there you want. The manifest for that one is...

 *= require_self
 *= require_tree ./all

Then your themes, each one with it's own folder:

/app/assets/stylesheets/theme-1/

it's manifest:

   *= require_self
   *= require_tree ./theme-1

So your second theme would be the same (with 2 instead of 1 for the folder name and in the manifest).

to make these work in the asset pipeline

In your production.rb file add the following

  config.assets.precompile += %w( application-all.css application-theme-1.css application-theme-2.css, etc.)

I do store my themes tied to a client site and serve dynamically, which also allows for me to change at runtime. In one of my controllers (or application if this is a site wide setting):

class MyController < ApplicationController
  layout :serve_layout
...
  def serve_layout
    #do what you need to call your layout / theme...    
  end

Hope this helps someone else stuck in this boat.

like image 193
creativereason Avatar answered Dec 17 '22 15:12

creativereason