Wim Haanstra
Wim Haanstra

Reputation: 5998

Use a different folder for assets

For a Rails application I am making I want to be able to switch 'themes' using a configuration file. The theme does not need to switch dynamically (while running, but will be known when the application starts).

I moved my stylesheets directory out of my assets directory, to a folder called : /app/themes/[themename]/assets/stylesheets.

The idea is to have multiple folders in the /app/themes directory, which can be used by the application.

REMARK: I didn't move my javascripts folder from the assets folder, because I still want to use that globally.

In my layout I use the following code, to load controller specific stylesheets:

<%= stylesheet_link_tag "#{controller_name}" if MyApp::Application.assets.find_asset("#{controller_name}") %>

Of course, my application no longer knows where my assets are and it serves me a page, where the assets are not loading (because of the if check mentioned above).

I added the following code to my config/initializers/assets.rb to make sure it also loads the assets from the theme directory:

Dir.glob("#{Rails.root}/app/themes/#{Settings.site.theme}/assets/**/").each do |path|
  Rails.application.config.assets.paths << path
end

Settings.site.theme is a string value which is filled correctly and now the stylesheets actually load on the website. So YAY!

But here is the thing, the minute I change the config.assets.compile to false, it all fails (so on test and production).

MyApp::Application.assets.find_asset("#{controller_name}") is throwing the exception undefined methodfind_asset' for nil:NilClass`.

I am on Rails 5.0.0.1.

Anyone got an idea how to fix this?

Upvotes: 0

Views: 570

Answers (1)

Ivan Zarea
Ivan Zarea

Reputation: 2174

I think a simpler way would be to namespace the themes under the stylesheets. That is, have a folder structure like this:

- app
  - assets
    - stylesheets
      - theme-blue
        - application.scss
      - theme-red
        - application.scss
    - javascripts
      - application.js

And then, in your layout file, you just point the stylesheet_link_tag to theme-blue/application, like this:

<%= stylesheet_link_tag "theme-blue/application" %>

Another way to do this is have multiple layouts, one for theme-blue and another one for theme-red. In the controller, do

class BlueController < ApplicationController
  layout "theme_blue"
end

And the file app/views/layouts/theme_blue.html.erb will require the right css file.

You might need to add the scss files to config/assets.rb, but Rails will tell you if you need that.

Upvotes: 1

Related Questions