Using <% in Underscore.js templating without parsing it - templates

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 %>

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.

What is '<%%' in ERB in Rails?

I have bean seen code of scaffold in rails. I found
<%% breadcrumb_add "<%= plural_table_name.capitalize %>", <%= plural_table_name %>_path %>
<%%= render 'form' %>
https://github.com/rails/rails/blob/3fcc0ca99107fa57110421b392f5854555f17fe2/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
What is <%% and how to use?
<%% in Erb produces a literal <% in the output. You can use it if you want the output of your template to also be Erb, which is what is happening in the Rails example you link to.
In your code, the output will be something like (if the variable plural_table_name is things):
<% breadcrumb_add "Things", thing_path %>
<%= render 'form' %>
which itself is Erb.

Rails .each enumerator with a special case for the first line

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.

ransack search # rails 4

When I am searching for gender field say "male", it searches for "male" and "female" as "male" keywork is in "female" too.
So How can I use ransack in rails so that it matches for exact keyword instead of any partial group of chars.
PS:similarly how can I enable or disable the exact or partial key match in RANSACK gem.
I believe you could just do
<%= search_form_for #q do |f| %>
<%= f.label :gender_eq, "Gender:" %>
<%= f.search_field :gender_eq %>
<% end %>
that will tell the search to look for the exact string of your input
Here is some of the info from the developer on how it's used.
https://github.com/activerecord-hackery/ransack#in-your-view
I believe the way you do your search is <%= (field_name)_cont ... %> cont means contains.
What you want is _eq, change your view into <%= (field_name)_eq ... %> and it should work.
For more info:
https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching