How to structure a layout template in Haml - ruby

I have a web page that uses Haml for layouts. "layout.haml" is a separate layout file which is used when rendering any actual Haml page.
layout.haml looks something like:
-# layout.haml
!!! XML
!!!
%html
%head
...
%body
...
#content= yield
This is of course already in the document's <body> so manipulating things in the header is not directly possible. For instance <title> is changed via #title. A bigger problem is the fact that every page-specific JavaScript needs to be loaded in the body. Moreover, layout.haml already contains JavaScript, so jQuery is usually instantiated multiple times.
Are there any suggestions for a better template structure?

This solution is for Ruby on Rails only:
You can use yield(:location) and the content_for(:location) methods. "Using the content_for Method" has more information.
layout.haml:
!!!
%html
%head
%title= yield(:title)
= yield(:head)
%body
= yield
view.haml:
- content_for(:title, 'My title')
- content_for(:head) do
= javascript_include_tag :foo
%h1 My view!

I use partials:
!!!
%html
= partial('trst_sys/shared/html-head')
%body{:id => "srv",:'data-lang' => current_lang}
#main.wrap
%header#header
= partial('trst_sys/shared/header')
%nav#menu
= partial('trst_sys/shared/menu')
%section#content
%article#xhr_content
= yield
%article#xhr_msg.hidden
%section#sidebar
= partial('trst_sys/shared/sidebar')
%section#main_footer.wrap
%footer#footer.wrap
= partial('trst_sys/shared/footer')

Related

How do you create pretty json in CHEF (ruby)

How would you make an erb template that has human readable json?
The following code works, but it makes a flat json file
default.rb
default['foo']['bar'] = { :herp => 'true', :derp => 42 }
recipe.rb
template "foo.json" do
source 'foo.json.erb'
variables :settings => node['foo']['bar'].to_json
action :create
end
foo.json.erb
<%= #settings %>
Similar SO questions
Chef and ruby templates - how to loop though key value pairs?
How can I "pretty" format my JSON output in Ruby on Rails?
As pointed out by this SO Answer .erb templates are great for HTML, and XML, but is not good for json.
Luckily, CHEF uses its own json library which has support for this using .to_json_pretty
#coderanger in IRC, pointed out that you can use this library right inside the recipe. This article shows more extensively how to use chef helpers in recipes.
default.rb
# if ['foo']['bar'] is null, to_json_pretty() will error
default['foo']['bar'] = {}
recipe/foo.rb
pretty_settings = Chef::JSONCompat.to_json_pretty(node['foo']['bar'])
template "foo.json" do
source 'foo.json.erb'
variables :settings => pretty_settings
action :create
end
Or more concise as pointed out by YMMV
default.rb
# if ['foo']['bar'] is null, to_json_pretty() will error
default['foo']['bar'] = {}
recipe/foo.rb
template "foo.json" do
source 'foo.json.erb'
variables :settings => node['foo']['bar']
action :create
end
templates/foo.json.erb
<%= Chef::JSONCompat.to_json_pretty(#settings) %>
Something like this would also work:
file "/var/my-file.json" do
content Chef::JSONCompat.to_json_pretty(node['foo']['bar'].to_hash)
end
<%= Chef::JSONCompat.to_json_pretty(#settings) %> Works like Charm !!

How to rendering partials within a partials in middleman

I have some Haml partials, many of which contain the boilerplate
.container
.row
.col-lg-12
When I try to abstract that out ala = partial "site_section", I get:
syntax error, unexpected keyword_end, expecting end-of-input end;end;end;end
I'm using ruby 2.2.2.
How do I render a Haml partial within a Haml partial in Middleman?
Thanks
update
This is apparently some kind of special case dealing with my partial (above). I have other partials-within-partials rendering just fine.
update
With respect to this this repo, the layout would actually be:
_site_section:
.container
.row
.col-lg-12
_nested_section:
= partial "site_section"
MOAR (nested) HAML
index.haml:
=partial "nested_section"
Because of the way HAML works the following is invalid:
= partial "site_section"
MOAR (nested) HAML
If you want to add more text or HAML then you can achieve it for example by putting the text at the same level of the previous line
= partial "site_section"
MOAR (nested) HAML
Or nesting it within a div:
= partial "site_section"
.more
MOAR (nested) HAML
So If what you are trying to do is to nest extra HAML to the output of the site_section partial, then you have to put the nested extra HAML in the nested partial:
.container
.row
.col-lg-12
= partial 'nested_stuff'
= partial 'nested_stuff'
Hope this helps, I updated the repo with the working example.

passing return (string) value into erb input value

Problem:
I want it to be able to pass the return value into an HTML ERB page(see result form below). I have tried many of the solutions on here and other sites and have yet to find one that fixes my problem. I included the full code in case I missed something.
NOTE: I get the return value and can bring up the results form but the return value is not passing. I already posted this but solution given did NOT help. This includes the change recommended to me. It appears adding #{output} so the redirect in the main code causes a "The connection was reset" error which makes no sense what-so-ever.
Main Code:
file name: */projects/webhosted_custom_fibonacci_calculator.rb
require "rubygems"
require "sinatra"
require_relative 'fibonacci_calculator.rb'
require "erb"
include Calculator
get '/' do
redirect ("/calculate")
end
get '/calculate' do
erb :calculator_form, :locals => {:calculator => session[:calculator]}
end
post '/calculate' do
num1 = params['firstnum'].to_i
num2 = params['secondnum'].to_i
output = Calculator.run(num1, num2)
redirect ("/results_form?results=#{output}")
end
get '/results_form' do
erb :results_form, :locals => {:results => params[:results]}
end
Result form:
File name: */projects/views/results_form.erb
<html>
<head>
<title>Fibonacci Calculator</title>
</head>
<body>
<h1>Results</h1>
Result: <%= results %>
</body>
</html>

RDiscount :generate_toc with Sinatra

So I have sinatra setup with Rdiscount to render a markdown file with a HAML layout. This all works but I want RDiscount to generate a table of contents based on the headers in my haml file. I've tried setting it in the sinatra configuration.
set :markdown, :generate_toc => true
but that doesn't seem to work.
I've also tried doing it when I render the markdown like so:
markdown :PAGENAMEHERE, :layout => :'layouts/PAGENAMEHERE', :generate_toc => true
which also doesn't work.
Is this even possible? If it is, what am I doing wrong?
While #three's answer helped me a lot, I would like to show a perhaps more general solution:
class MDWithTOC < ::Tilt::RDiscountTemplate
def flags
[:generate_toc]
end
end
Tilt.register MDWithTOC, 'md'
Here we override the flags method of the RDiscount Tilt template handler and regiter it as a handler for the md format.
Now you can use the md helper as always and it will generate the TOC.
This should work:
get '/' do
text = File.read('README.md')
markdown = RDiscount.new(text, :generate_toc)
body = markdown.to_html
haml :home, :layout => true, :locals => {:body => body}
end
You create the body directly via RDiscount and include it as plain HTML in your HAML layout. Whatever prevented toc creation should work this way natively. I found the solution via https://github.com/mjijackson/markdown/blob/master/app.rb

Selectively using yield_content in Padrino application.haml template

In a Haml based Padrino solution I have an application.haml like this:
!!!
%html
%head
%title "blah"
%body
#header
= yield_content :headcontent
#container
...
For :headcontent, in my page (e.g. index.haml) I have
- content_for :headcontent do
#headcontent
%h2= "Index header stuff"
#content
...
What I want to do is make it so that content pages like index.haml can optionally specify - content for :headcontent. That is I want application.haml to contain some default :headcontent that only is rendered if a page does not do - content for :headcontent.
How do I do this?
In your main file, you should be able to use content_for?, like this:
- if content_for?(:headcontent)
= yield_content :headcontent
- else
something else

Resources