themes_on_rails icon indicating copy to clipboard operation
themes_on_rails copied to clipboard

Fallbacks to base theme and inheritance

Open iamdriz opened this issue 7 years ago • 9 comments

How can we have it so that if no theme is found it falls back to the default app/views?

And using this same mechanism would it be possible to get it to first look in the theme folder, then have a parent theme to fallback to and then finally the default Rails folder if it can't be found.

iamdriz avatar Oct 23 '17 11:10 iamdriz

As given in the README, you could either define method or Proc for this in the controller.

theme :default_theme

private

def default_theme
  theme || parent_theme || "layout_name"
end

yogeshjain999 avatar Oct 23 '17 12:10 yogeshjain999

@yogeshjain999 So you pass the default layout as the fallback theme?

iamdriz avatar Oct 24 '17 10:10 iamdriz

Correct @iamdriz. It is because search locations includes app/themes and app/views Dir.

yogeshjain999 avatar Oct 24 '17 10:10 yogeshjain999

@yogeshjain999 That being said though.... If I have:

theme :theme_resolver

private

def theme_resolver
  'a_theme_that_doesnt_exist' || 'a_theme_that_does_exist' || 'application'
end

I'm finding that instead of it falling back to the 'a_theme_that_does_exist' it falls straight back to the default views. Probably because I have a value for the first theme (even though it doesn't exist) in the operator and it will try and find that and then just fallback... what I want it to do is fallback on a view-basis to the next operator value and then the default views if those can't be found either. To achieve that, would I need to manually check if the view requested existed first based on the currently requested theme and then try the next one until defaulting to application?

iamdriz avatar Oct 24 '17 10:10 iamdriz

That being said, easiest way I can see is doing it like,

def theme_resolver
  theme_present?('a_theme_that_doesnt_exist') || 'application'
end

def theme_present?(name)
  return name if Rails.application.paths["app/themes/#{name}"].present?
end

yogeshjain999 avatar Oct 24 '17 11:10 yogeshjain999

@yogeshjain999 The theme may exist but the view for that particular request may not.

iamdriz avatar Oct 24 '17 11:10 iamdriz

In order to get the fallback theme to work I had to do:

before_action :fallback_theme
def fallback_theme
  self.prepend_view_path 'app/themes/fallback_theme/views'
end

iamdriz avatar Oct 24 '17 13:10 iamdriz

It also turns out that it doesn't actually use the fallback string:

def theme_resolver
  params[:theme] || 'I CAN PUT ANYTHING HERE'
end

So it would be good to pass back a nil if no theme is specified. Rather than a string that is basically ignored as the default paths are already in the view_paths. Just feels a bit of a hack.

iamdriz avatar Oct 24 '17 14:10 iamdriz

After playing around with this I've come to find that building a Rails Engine is probably a better way forward as then it means you can have everything a Rails app would have on a theme basis.

iamdriz avatar Oct 24 '17 16:10 iamdriz