How to handle template (layouts) inheritance in Jekyll? - ruby-on-rails

I want to have a template "_layouts/template1.html" extend (Django-style) a template _layouts/default.html.
I'm putting this as a YAML front matter in _layouts/template1.html
---
layout: default
---
{{page.content}}
but apparently it doesn't work the way I'd like it to work (all the additional markup that is present in template1.html but IS NOT in default.html does not render). It looks like the file that uses template1 layout purely extends default.html.
Is there any way to have layouts inheritance in Jekyll?

What you mean is simply {{ content }}.
Yes, layouts can be piped. In your case, if a page uses template1 layout, it is the content for template1. Then, the result of template1 is the content for default.

Jekyll's Liquid templates extend pretty easily, you just have to be sure you're extending and not overwriting your desired template.
You may actually want to extend page and not default.
So, in your template Front Matter:
---
layout:page
---

Try the Liquid Inheritance Gem: https://github.com/danwrong/liquid-inheritance
Reference: http://www.sameratiani.com/2011/10/22/get-jekyll-working-with-liquid-inheritance.html

template1.html from your example will extend default.html as long as the latter contains a {{ content }} block. See here for example. What it won't do is it won't overwrite anything that default.html already contains. For that you'll need the Liquid Inheritance Gem, as mentioned by #juddlyon.

Related

Understanding the purpose of the underscore in grails templates

Working with grails templates and the render method isn't that hard.
I worked with it for a while now.
It's okay for me to deal with the 'Convention over Configuration'. And so it is with the needed underscore "_" at the beginning of the filename of a template .gsp file.
I'm not that experienced with programming in general, I'm doing an apprenticeship as a 'IT-specialist for application development' since 2,5 years now. So my background knowledge isn't that big yet.
But I'd now really like to understand what exactly the purpose of that underscore is.
How's grails dealing with files with a leading underscore in comparison to those without it?
String view='/path/to/file'
def model= [template:view,instance:bean]
render(view:view, model:model)
this tells that template is '/path/to/_file.gsp' when it renders the template bit
when it renders view it looks for '/path/to/file.gsp'
so when you do render view it looks for files without underscore
when you do render template it looks for those with underscore
above example does both to explain how it works
As others have already pointed out the underscore indicates that the file is a template. However, the question still remains "what's the purpose?"
The purpose of a template is to provide a way to render a reusable fragment of view code. This allows you to compose very complex views (e.g. think functional decomposition). Templates aren't decorated by the sitemesh layout. This is very important when doing partial page updates with AJAX (or similar technology).
The documentation actually explains templates quite well.

How to override erb with liquid?

I've added a theming directory to my app as described here, using prepend_view_path. It works as expected. I can now add a view structure in my app under app/themes/my_theme/views
Now, I want to be able to override erb templates by dropping in a
.liquid file, which will render right off the controller action.
For example, I want to override app/views/pages/home.html.erb:
<h1><%= t 'it_works' %></h1>
...with app/themes/my_theme/views/pages/home.liquid
<h1>It works with {{ "liquid" }}</h1>
I don't want to have to specify an array of view paths (upkeep would be awful), but just add .liquid as a layer to the templating engine. Maybe, however, have a blacklist of protected views that cannot be overridden (such as app/views/admin/*)
Do you have a liquid template handler? Otherwise Rails won't know what you want to do with .liquid files. See this blog post: http://royvandermeij.com/blog/2011/09/21/create-a-liquid-handler-for-rails-3-dot-1/
For your second question: not using a theme for app/views/admin/* you should make sure you have an AdminController that does not prepend_view_path.
According to the documentation you can use prepend_view_path
Add the following to your ApplicationController:
before_filter :set_theme_path
def set_theme_path
prepend_view_path "app/themes/#{current_theme}"
end
So Rails should then look for any views in your theme specific directory in preference to the default views in app/views/**/*

how do i dynamically change my format rendering engine in rails?

My default templating engine is haml, but I would to sometimes change it to erb if i specify a specific parameter?
For example, I am pasting in some html code and would just like to test the code without HAML complaining about its format.
Any idea how to do this?
do something like:
if params[:render_erb]
render 'file.html.erb'
else
render 'file.html.haml'
end
and call the action with ?render_erb=true
or
render "file.html.#{params[:render]}" ir params[:render]
and call it ?render=haml or ?render=erb (or nothing and it will use the default
at the end of the controller's action that you are using
Am I wrong that you simply need to save file as your_file.html.erb instead of your_file.html.haml?
You can use different templates in the same application, and you can use different template engines for views, partials, and layouts, but as far as I know you can't duck in and out of multiple template engines within the same template file.
If you just want to drop some code in using a different template language, then I'd put it in a separate partial. That certainly seems easiest in this particular case.

Rails 3 multiple layout question

Can i have more than one layout per action -
What i want is - "show.html.erb" template to be contained in "layouts/users.html.erb" and this to be contained in "layouts/application.html.erb"
Basically I want application to be the global layout container, but i also want to use intermediate layouts containers between the action template & the final application layout.
If yes, can you point me to some help topics, links.
See the "Nested Layouts" section of the "Layouts and Rendering" guide.
You can use the Nested-Layout plugin:
http://nested-layouts.rubyforge.org
You can follow the instructions in "Sorta Nested Layouts":
http://mattmccray.com/archive/2007/02/19/Sorta_Nested_Layouts/
But what I would recommend is using named yield and content_for statements:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts
This approach lets you specify content for specific parts of your page and generally results in much cleaner and more readable code.

Fallback format in rails

for my CMs i want to be able to easily add new themes, my idea was to simply add a mime type for the new theme (so application.theme1.erb would work).
but for 99% of the themes im not going to want to change the views, well not all of them.
is there someway to have rails fall back on html if the themed view isnt present?
I'm pretty new to Rails, so this might not be a perfect answer:
you might want to try using querystring parameters as part of the route like described here:
http://guides.rubyonrails.org/routing.html#querystring-parameters
so eventually something like this would work
map.connect ':theme/:controller/:action/:id'
As I understand it, the theme would be available as params[:theme] in the controller. If no theme is specified you probably have to add another route like
map.connect '/:controller/:action/:id'
to handle that case.
In the i18n guide something similar is described for locales: http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-url-params
Hope that helps.
It depends on how much of the layout you want to change with the themes.
If you build your HTML right, most of the things can be done through css. (changing fonts, colours, where the stuff show up)
Then it is quite easy to add just a theme parameter to style it.
If you don't want to do that, you can always create a separate layout for it, and assign that depending on the parameters passed in (or even set it as a session variable so you won't have it in the url).
Basically, for the default theme, you stick to the layouts/application.erb, then you have say layouts/theme1.erb which you then assign with a method
class ApplicationController
layout :decide_layout
def decide_layout
#session[:layout] || 'application'
end
end
Customizing the views would be possible just by doing something like this in your actions:
def my_action
render "my_action_#{#session[:layout]}" if #session[:layout]
end
if #session[:layout] is not set, it will render the default, otherwise it will render your themed view.
Of course, if you set the layout depending on user input, make sure to sanitize and check the layout parameter before.
I've just had this same problem with mobile_fu, which sets the format to :mobile for mobile requests.
It turns out that if an :action.:format.erb template isn't available, Rails will serve :action.rhtml as a replacement in any format.
I can't say whether this will work for layouts, but it certainly works for actions

Resources