Rails erb vs gsub dynamic template performance - ruby-on-rails

In my project, I am using the ERB as template engine. We have one page which used ERB template and it's loaded within 5-7 seconds.
The same page we changed it into dynamic template, the template values are stored in the database.
sample template
<p> {{name}} </p>
<p> {{address}} </p>
<p> {{mobile number}} </p>
For applying the actual values over dynamic template, i have used the gsub. This case the same page takes load time as 16-20 seconds. I used 17 gsub over dynamic template.
How erb rendering is fast? (Because i am using the same content
before and after dynamic template)
Is there any way to increase the performance?
Note:
Compared to 'gsub' method, 'sub' method is fast. But in my case i need to use global sub (gsub).

In my case, the whole page is like a dynamic template with 20 tags. In that case gsub is not a correct solution to replace the 20 tags.
Client Side:
I have used the client side template engine called Handlebar.js. Using this my page loads with normal speed.
Server Side:
https://github.com/Shopify/liquid

If you store templates in database then you could use appropriate tools to render them. If it's erb then just use ERB, don't gsub variables manually. The reason why erb is so much faster than manual gsub is because erb template gets compiled to ruby code (like "Foo <%= bar %>" becomes "Foo " + bar) and executed.
As I understand you want to store your templates in database and render them both on server and client. You can use mustache for that, it's framework-agnostic and safe to run on server.

Related

Safe Rails HTML translations

Following the rails guides as per the posting title, the YAML local files were set in a Rails 6.1.3 application as follows:
authorisation_request: Payment to be authorised; </br>Final <b>exact charge</b> </br>will reflect <b>delivered goods</b>.
authorisation_request_html: Payment to be authorised; </br>Final <b>exact charge</b> </br>will reflect <b>delivered goods</b>.
In the view, three experiments were conducted:
<i><%= t('cart.authorisation_request').capitalize %></i>
<i><%= raw t('cart.authorisation_request_html').capitalize %></i>
<i><%= t('cart.authorisation_request_html').capitalize %></i>
The first one rendered the tags as expected straight text, the middle one rendered as expected both the break and bold tags.
But the last one was rendered identical to the first. What am I missing?
When a translation key has the _html suffix, you can call it as if it did not, and it will automatically treat the key as HTML safe.
The way you are displaying the translation key is not as intended, instead of doing:
<%= t('cart.authorisation_request_html').capitalize %>
You should be doing:
<%= t('cart.authorisation_request').capitalize %>
Then the I18n system will see that there is an _html-suffixed variant, and mark that as HTML safe to display as-is. The way you are doing it now, the system would be looking for a key named authorization_request_html_html (double suffixed) and not find it.
More info on Safe HTML Translations: https://guides.rubyonrails.org/i18n.html#using-safe-html-translations
As a side-note, you should probably be capitalizing your source translated text, and not modifying it afterwards with the .capitalize helper. If that text were translated to another language, the capitalization could probably look pretty strange in some languages.

Rails translation performance impact <%= raw t( vs. <%= t(

I am building a multilingual application using rails-i18n Ruby on Rails.
Most of content (and DB entries) I have to translate is pure text, though part of it has some embedded html.
I was thinking of using <%= raw t('translation_key') %> instead of the straight <%= t('translation_key') %> to account for future changes that might include html.
If I adopt <%= raw t('translation_key') %> throughout the all website, am I going to get any (negative) impact when it comes to
website performance
website security
You just just append _html to your tag keys to handle HTML in translation tags:
en:
key_one: test text
key_one_html: <p>test text</p>
Then the standard code will work:
<%= t('key_one_html') %>
Performance aspect:
The performance impact should be negligible. Calling raw copies the parameter into a new string (an ActiveSupport::SafeBuffer to be precise) with its html_safe flag set to true. On the other hand there is no longer HTML escaping performed on that string.
Security aspect:
There are more substantial drawbacks to using raw everywhere.
You say your translations are read from the database. Can the user edit these translations? If so...
You risk HTML injections: A malicious user could just enter a <script> tag.
All your translations must to be HTML safe from now on. That means you have to manually escape all your translations, i.e. you have to replace <,>, and &.
Alternatives:
There are other options if you need to incorporate HTML into your translations:
Use the _html suffix judiciously to prevent automatic escaping
Use localized views and partials, i.e. index.en.html, _footer.de-DE.html to translate larger parts of your views.
To streamline translation of database entries, you try
Globalize
hstore_translate (PostgreSQL only)
Conclusion:
Using raw everywhere will lead to a lot of problems along the road. Save yourself a lot of trouble and just use it "as needed".
You could also use the globalize gem for bigger text / html sections of content.
https://github.com/globalize/globalize/blob/master/README.md
It also supports eager loading if you're worried about performance.

Using a single html template for Rail view and Angular Template

I have a Ruby on Rails app that loads a single page Angular JS Web App when the user is logged in, and serves static info pages via RoR views when the user is not logged in.
The angular templates are in 'app/assets/templates/' and the rails files are in 'app/views'.
I have a text heavy html page that I would like re-use with both rails and angular. I've tried accessing the rails view from my angular $routeProvider, setting templateURL to the path of the view. This causes more than one instance of angular to load and it gets stuck in a loop.
app.config ($routeProvider) ->
$routeProvider.when('/features/',
templateUrl: '/views/features.html'
)
I've tried rendering the file in my assets/templates folder through a rails view. That doesn't work either since rails can't find the partial.
= render 'assets/templates/features.html'
Does anyone know how I might be able to use a single template for both?
I'm mot sure what exactly you mean by text heavy page. But what about other solution - extract all text to JSON file with keys (some sort of translation file). For example:
{ "title1": "Title", "paragraph1": "lore up sum. .." }
Then you can load this JSON in your rails controller and pass it to view that render text parts from it.
<h1><%= #text ['title1'] %></h1>
<p><%= #text['paragraph1'] %></p>
And as well load JSON as resource in your angular app and pass it to view.
<h1>{{ text.title1 }}</h1>
<p>{{ text.paragraph1 }}</p>
If your text is somehow structured you can make use if it and automate the view with loops, conditions etc and so save repeated parts even more.

Safely rendering a user's template/view?

I have a model which has a template field. This template is HTML and has variables which get substituted. This template is then converted into a PDF using wicked_pdf.
How should I take the template which the user enters and safely do variable substitution? Allowing it to be an ERB template seems to be setting myself up for some huge security holes. What safe solutions are there?
Edit:
So, for example, I have my template class/model which has two fields, a name and an HTML field. This is a user editable class. There will be specific variables available to the HTML in the template class (Company Name, price, etc.). I am hoping to use a HTML templating system, but since this is user created content, it isn't trusted. Only variable substitution will be done, nothing more.
Rails provides a couple of helper functions, namely hto escape values on display for preventing such behavior.
<%= h #user.name %>
h is an alias of html_escape

Better way to implement an Html Helper method?

I created an html helper
Html.BreadCrumb(IDictionary<string, string> crumbs)
Where the first string is the label and the second string is the URL.
The helper creates the html required (an unordered list, some classes for first element, current element, last element, dead element and separators etc)
All working nice, but I do this by creating a stringbuilder, pumping all the html in it and returning the stringbuilder's content as a string.
I figure in this example it doesn't matter all that much, but what if an Html helper is churning out a big load of html? Isn't there a way to push it to Response.Write instead of a stringbuilder?
Or any other issues/improvements you have?
BTW we have a naming pattern in ASP.NET MVC for the various rendering techniques.
Helpers that return a string of what they are should be named what they are. For example, Url.Action() and Html.TextBox() return those exact items. Thus, these helpers should be used with the <%= %> syntax.
Helpers that render directly to the output stream should start with Render. For example, Html.RenderPartial(). These are used with the <% %> syntax.
Helpers that use the IDisposable pattern should be named with Begin/End. For example, Html.BeginForm() and Html.EndForm(). These should also be used with the <% %> syntax.
Thanks,
Eilon
It certainly is possible to use Response.Write instead of returning a string; see the source for System.Web.Mvc.Ajax.Form (in AjaxExtensions.cs) in the MVC source for an example.
You then call the helper with <% instead of <%=.
Will it be any faster? I doubt it, but it's easy to test.
I don't think you will have any performance problems as long as the size of the HTML pages you produce is reasonable. And when you really start to create pages of megabytes in size, then you should ask yourself, why are you creating such huge HTML files?

Resources