I am trying to modify one of my templates so that a certain include is called on all but two Page types.
The code I am using is:
<% if ClassName != BusinessPage || ClassName != BusinessSubPage %>
... some code here
<% end_if %>
This does not work as the if statement passes on all page types and the code in the if statement is triggered.
If I shorten the code to just one page type it gives the expected results on the page type:
<% if ClassName != BusinessPage %>
... some code here
<% end_if %>
Is there some unexpected issue with using ClassName as a conditional in an if statement that I need to be aware of that would explain my issues?
Your if statement logic isn't quite right. What you want is to use && (AND) instead of || (OR):
<% if $ClassName != "BusinessPage" && $ClassName != "BusinessSubPage" %>
Here is a logic table showing the results of three different class names.
$ClassName | $CN != BusinessPage | $CN != BusinessSubPage | OR | AND |
----------------|---------------------|------------------------|-------|-------|
ABC | true | true | true | true |
BusinessPage | false | true | true | false |
BusinessSubPage | true | false | true | false |
The OR column shows that no matter what the ClassName the result is always true. This is why the if statement always passed.
An alternative is to put the logic in the Page_Controller. This makes the templates easier to read when the logic gets complicated.
Page.php
public function BusinessTemplate() {
return in_array($this->ClassName, array('BusinessPage', 'BusinessSubPage'));
}
Page.ss
<% if not $BusinessTemplate %>
enter code here
<% end_if %>
Related
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.
I am trying to drill down some searches in my app using time intervals....posts in the last day, last week, last month. I am trying to be DRY and write a search controller method that will handle this for me. I am having probelms passing in the time variable. See the form below. #search_term is the search term and hidden becasue for this form as an example, all the client sees is a link saying "last 24 hours"
<%= form_tag time_searches_path do %>
<%= hidden_field_tag :search_task, #search_term %>
<%= hidden_field_tag :time, "24" %>
<%= hidden_field_tag :Klass, Micropost %>
<%= submit_tag "Last 24 hours", class: 'Criteria'%>
<% end %>
Then I have a helper method that is included in my search controller.....
def get_time_interval time
if time == "24"
#time_variable = 1.day.ago
elsif time == "week"
#time_variable = 1.week.ago
elsif time == "month"
#time_variable = 1.month.ago
end
end
Then I add the time_variable into my controller action
def search
model = params[:Klass]
klass = model.constantize
time = params[:time]
get_time_interval time
#search = Sunspot.search [klass] do
fulltext params[:search_task]
with(:created_at).greater_than(#time_variable)
end
end
Clearly this is wrong. I assuming i need some form of metaprogramming. I am new to rails to don't really know how to proceed.
Error I get is
undefined method `gsub' for nil:nilclass
And it highlights the line with the time variable in the controller
I'm trying to put an enumerator to run over the top of a (refills/bourbon) front end framework. The element is a tab accordian which has repeatable elements but a special is-active class tag which flags to javascript which one should be expanded and the focus of a users attention.
I want to design an enumerator to create tabs and fill content based on how many records there are in ActiveRecord so I'm using an enumerator - but is there a smart way I can create a clean exception for the first <a> it outputs so it includes the is-active tag?
Currently my murky hack is below:
<div class="vertical-tabs-container">
<div class="vertical-tabs">
<% tab_num = 0 %>
<% #user.items.each do |item| %>
<% tab_num += 1 %>
<% if tab_num = 1 %>
<%= content_tag( :a, #user.item, :class=>"js-vertical-tab vertical-tab is-active, :rel="tab#{tab_num}", :href="javascript:void(0) %>
<% else %>
<%= content_tag( :a, #user.item, :class=>"js-vertical-tab vertical-tab, :rel="tab#{tab_num}", :href="javascript:void(0) %>
<% end %>
</div>
... content goes here...
</div>
There seems something deeply un-rails about that tab_num bit... and I sense a disturbance in the MVC force for putting this in my view... Plus this way I'd have to have another enumerator for the body element of the vertical-tabs-container...
Anyone got a better idea of how to do this neatly?
Firstly, this looks like it belongs in a helper or a presenter/decorator.
The code itself could be simplified. Helper method:
In your view:
<div class="vertical-tabs-container">
<div class="vertical-tabs">
<%= user_tabs(#user) %>
</div>
... content goes here...
</div>
Then in your helper:
def user_tabs(user)
output = ""
user.items.each_with_index do |item,i|
output << content_tag(:a, item, :class=>"js-vertical-tab vertical-tab #{i == 0 ? '' : 'is-active'", :rel="tab#{i}", :href="javascript:void(0)
end
output
end
However if you're going to start adding content and tabs seperately, take a look at draper and define methods for tab and body on the item element.
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
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 %>