converting puppet erb template to epp - templates

I'm trying to convert erb templates to epp (new company policy) and there isn't a lot of documentation on epp yet.
Here's what i have in erb:
<% filter.select{|x| x != 'filtertype'}.sort.each do |key, element| -%>
<%= key %>: '<%= element %>'
<% end -%>
it works great! however i have to find the equivalent for epp. I can get the "each" part to work, but the select method isn't working for me.
I'm stumped!
I tried something like:
<% $filter.select { |$x| $x != 'filtertype'}.each |$key, $element| { -%>
<%= $key %>: '<%= $element %>'
<% } -%>
this in particular errors on '|' for the $x.
I also tried:
<% $filter.select |$x| {$x != 'filtertype'}.each |$key, $element| { -%>
<%= $key %>: '<%= $element %>'
<% } -%>
but that gives me something like "Error while evaluating a Method call, select(): Wrong number of arguments given 1 for 3"
I've tried moving around the {} and changing them to (), but no luck.
does anyone have any ideas?
Thanks!

As Dominic Cleal mentions in the comment, select() is not a Puppet function, however filter() is and is the equivalent of select in Ruby.
Therefore:
Given a class:
class foo () {
# Some test data.
$filter = {
'filtertype' => 'foo',
'apples' => 1,
'bananas' => 2,
}
# How to declare the ERB template for comparison:
file { '/foo':
ensure => file,
content => template('foo/mytemplate.erb'),
}
# How to declare the EPP template for comparison:
file { '/bar':
ensure => file,
content => epp('foo/mytemplate.epp', {'filter' => $filter}),
}
}
Content of the ERB file exactly as given in the question:
<% #filter.select{|x| x != 'filtertype'}.sort.each do |key, element| -%>
<%= key %>: '<%= element %>'
<% end -%>
Content of an equivalent EPP file:
<% | Hash $filter | -%>
<% include stdlib -%>
<% $filter.keys.sort.filter |$k| {$k != 'filtertype'}.each |$k| { -%>
<%= $k %>: '<%= $filter[$k] %>'
<% } -%>
Things to note:
1) You need include stdlib to access the keys and sort functions.
2) The variable name $filter now clashes with the built-in Puppet function filter(), which is syntactically fine, but confusing, so you would consider renaming the $filter variable to something else for clarity.
Also, if you don't care about sorting the keys, then I could make what you tried work using:
<% | Hash $filter | -%>
<% $filter.filter |$k| {$k[0] != 'filtertype'}.each |$k, $v| { -%>
<%= $k %>: '<%= $v %>'
<% } -%>
See also here where I just answered a similar question.

Related

How to include a variable inside <% include > in a template ejs file?

I have a list of files in a folder that I need to serve inside the parent as a child template. I would like to do something like this:
<% var noScriptBody = 'message-scriptless.ejs' %>
<% include noScriptBody %>
or <%include <%= noScriptBody %>/message-scriptless' %> where <%= noScriptBody %> are the specific child template to include.
For example, I want to include <% include carousel/message-scriptless %> and <% include modal/message-scriptless %> where the path is variable ['carousel', 'modal', etc]
You can include dynamic template like this
for ex. your array passed is pathArray = ['carousel', 'modal', etc]
<% for (const path in pathArray) { %>
<%- include(path +'/message-scriptless.ejs') %>
<% } %>
Here, we iterate through the pathArray & include message-scriptless.ejs from each folder as shown in code above
Please correct me if I misunderstood your requirements
For an example, you can look at this code below: index.ejs
<!-- Only show text -->
<% var noScriptBody = 'message-scriptless' %>
<%= noScriptBody %>
<!-- Show template -->
<% var noScript = 'message-scriptless' %>
<%- include(noScript) -%>
<!-- Show template `message-scriptless` from `carousel` directory -->
<% var carouselMessageSciptLess= 'carousel/message-scriptless' %>
<%- include(carouselMessageSciptLess) -%>
Make sure in the same directory, you've a file message-scriptless.ejs.
Updated: For mapping your variable, you can use this code below:
<% arrayPath.forEach(function(path){
include(path + '/message-scriptless');
}) %>;
From code above, this is an example directory structure:
src > app.js
views > index.ejs
views > message-scriptless.ejs
views > carousel > message-scriptless.ejs
package.json
For more information about this ejs, you can read this documentation.
For an example, you can look at my codeSandbox: https://codesandbox.io/s/example-ejs-app-mhgrh
I hope it can help you.

Globalize accessors on subset of available locales

By design, some classes will deal with only a subset of available languages.
the globalize-accessors gem is quite useful, however, the rendering requires that the following be defined
Class.globalize_attribute_names
so while available_locales = [:en, :ru, :fr, :de], the goal is to work with a smaller array [:en, :ru]
The documentation states Calling globalize_accessors with no options will therefore generate accessor methods for all translated fields and available languages. But the purported way to invoke is in the model
globalize_accessors :locales => [:en, :fr], :attributes => [:title]
How can the globalize_accessorsmethod refer to an array, something generated by the likes of
#post.owner.ownerlocales.pluck('locale')
(although the array values are quoted...)
A working solution found but that does not address the above question, is based on the fact that globalize-accessors
gives you access to methods: title_pl, title_en, title_pl=, title_en=
Thus, a controller method that generates a whitelist
#locales = []
#post.owner.ownerlocales.each do |ol|
locale = ol.locale
#locales.push(locale)
end
... then process in the view filtering out the globalize_processors from whitelist
<% Post.globalize_attribute_names.each do |lang| %>
<% my_string = lang.to_s %>
<% #locales.each do |locale| %>
<% checkstring = "_" + locale %>
<% if my_string.include? checkstring %>
<div class="row">
<%= t(lang[0..-4]) %> - <%= lang[-2, 2] %> <br />
<%= f.text_area lang, rows: "3" %>
</div>
<% end %>
<% end %>
<% end %>
Not efficient, functional.

Chef Recipe to create template with nested data

I am trying to create a chef recipe for my Amazon OpsWorks stack. I'd like to pass custom JSON data into the stack, and have the recipe create an .ini file for use with PHP's parse_ini_file() command.
What I Have Working
Currently, I can create a flat .ini file with the following:
JSON:
{
"settings_ini": {
"quantity": 1,
"width": 10,
"height": 20
}
}
The resulting settings.ini file is:
quantity = 1
width = 10
height = 20
Chef recipe:
template "/my/path/here/settings.ini" do
owner "www_data"
group "www_data"
mode "0644"
source "settings.ini.erb"
variables({
:settings_ini => node[:settings_ini]
})
end
Chef template "settings.ini.erb":
<% #settings_ini.each do |name, value| -%>
<%= name %> = <%= value %>
<% end -%>
What I'm Trying to Make Work
I'd like to change my JSON data to be this:
{
"settings_ini": {
"quantity": 1,
"attributes": {
"width": 10,
"height": 20
}
}
}
And I want my resulting settings.ini file to be this:
quantity = 1
[attributes]
width = 10
height = 20
Or, it could also be this:
quantity = 1
[attributes]width = 10
[attributes]height = 20
I need help modifying my settings.ini.erb template file to use the nested JSON data correctly.
You could use a recursive function.
Stick this into libraries/hash_to_ini.rb:
def hash_to_ini(hash, lines = [])
hash.each do |name, value|
unless value.is_a? Hash
lines << "#{name} = #{value}"
else
lines << "[#{name}]"
lines = hash_to_ini(value, lines)
end
end
return lines
end
Then in your template:
<% hash_to_ini(#settings_ini).each do |line| -%>
<%= line %>
<% end -%>
Why not just a second each loop?
<% #settings_ini.each do |section, data| -%>
[<%= section %>]
<% data.each do |name, value| -%>
<%= name %> = <%= value %>
<% end -%>
<% end -%>
This code is untested.. but I guess it should work.
You could also add some safety like done e.g. here and here

Conditions in underscore.js templates

How can we check a condition in underscore and print accordingly?
Sample code.
<% if(status==1){ %>
<%= status %>
<% } %>
Is there a way to remove the overlapping %> and <%= ??
I am a php developer and the above code in php would be :
<?php
if($status==1){
echo $status;
}
?>
Is there a way to echo in underscore like "echo"?
yes, try with print();
like:
<% if(status===1) {
print(status);
} %>
docs: http://underscorejs.org/#template

Using <% in Underscore.js templating without parsing it

Usually, if you use templating by Underscore.js, any expression that looks like <% ... %> and <%= ... %> is parsed by Underscore.js
How do I escape such a value, in case I want to embed the text <% ... %> inside the template?
To put it in other words: How can I tell Underscore.js to ignore something that looks like a placeholder, but that isn't a placeholder?
I guess I have to use some kind of escaping, but the usual \ won't work. If I type
_.template('<%= name %> ### \<%= name %>', { name: 'foo' });
I get foo ### foo as a result, which is obviously not what I wanted.
Update: To make more clear, what I want from the line above - it should result in
foo ### <%= name %>
If your final output is going to be HTML, you could replace < and > with their HTML escape code thingers:
_.template('<%= name %> ### <%= name %>', { name: 'foo' });
You could also modify Underscore's template settings to support these things, so that <%= ... %> means nothing to Underscore:
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
var t = _.template('{{name}} ### <%= name %>', { name: 'foo' });
For a non-html specific solution, use unicode character escape sequences to escape <, > and %. Using your example, this:
_.template('<%= name %> ### \u003C\u0025= name \u0025\u003E', { name: 'foo' });
Will output
foo ### <%= name %>