Use HTML inside a Rails translation file - html

I have some translations in my Rails application (config/locale/[en|de].yml) and I use it in my views with <%=t "teasers.welcome" %>. Example:
teasers:
welcome: "<strong>Welcome</strong> to the Website ..."
In Rails 2.3.8 this works just fine, with Rails 3, the HTML is escaped and translated to <... How can I prevent this form this translation and use HTML in my translation files like in Rails 2.3.8?

Other than using raw, there's an other undocumented (but official) way to do so.
All keys ending with _html are automatically rendered unescaped.
Rename the key from
teasers:
welcome: "<strong>Welcome</strong> to the Website ..."
to
teasers:
welcome_html: "<strong>Welcome</strong> to the Website ..."

I suppose it's because doing
<%= t("blah") %>
in rails 2.x, now is the equivalent of doing
<%=h t("blah") %>
when you're using rails 3.
From the release notes:
Switch to on-by-default XSS escaping
for rails.
To fix this, and once again from the release notes:
You no longer need to call h(string)
to escape HTML output, it is on by
default in all view templates. If you
want the unescaped string, call
raw(string).
So just replace
<%= t("blah") %>
by
<%= raw t("blah") %>

Related

A way to precompile slim templates on server side and pass HTML to VueJS in Rails app?

I'm trying to integrate Vue js in existing rails app with lots of slim templates. It would be nice if I could use vue directives in slim templates
(yes, it's possible), get an HTML and pass it to Vue instance for further development. I know that there are slim-lang loaders that compile slim to html, or that you can use slim syntax inside <template lang="slim">.
But I don't want to separately send the result of every single ruby/rails method via AJAX. I want Rails to do its job and give the resulting HTML to Vue instance. Any thoughts and suggestions about this?
The solution I've found is quite simple. All you need to do is wrap your slim markup inside of vue component tag in your .slim views, and add inline-template attribute to it.
Example:
# header.html.slim
<v-header inline-template>
header
nav
- categories.each do |category|
= link_to category.name, category, '#click.prevent': 'doSomething'
</v-header>
or
v-header inline-template=""
header
nav
- categories.each do |category|
= link_to category.name, category, '#click': 'doSomething'
Ruby code will be executed first, template engine will convert everything to html with vue directives, then Vue will recognize its directives and take control of the markup. After I implemented this, I got rid of jquery and asset pipeline. But the views are the same. I did not migrate any of html files to vue components. With this feature, you can partially apply Vue js to your existing rails project and start writing modern javascript code.
There is no silver bullet to combine server-side and client-side templating. Even if you can render vue templates on the server the key context is missing (the interactive state of the page in the client).
There are some rather simple but flawed techniques that you could use to combine server-side and client rendering:
Create a controller that serves up your views
Rails.application.routes.draw do
scope 'templates' do
get '*path', to: 'templates#show'
end
end
class TemplatesController < ApplicationController
def show
if lookup_context.exists?(params[:path])
render template: params[:path]
else
head :not_found
end
end
end
require 'rails_helper'
RSpec.describe "Templates", type: :request do
describe "GET /template/*path" do
it "fetches template if it exists" do
get '/templates/foo/bar.html.erb'
expect(response).to have_http_status(200)
expect(response.body).to match "TEST"
end
it "returns 404 if it does not exist" do
get '/templates/foo/non_existant.html.erb'
expect(response).to have_http_status(:not_found)
end
end
end
However the devil is in details - this would only really work if your views are completely static and do not need any input data.
Render views without a layout
If you instead want to render normally from your controllers but not include the entire layout you can register a custom format:
# config/initializers/mime_types.rb
Mime::Type.register "text/x-html-template", :template
Sometimes you may need to stop spring in order for configuration changes to be picked up.
You can then disable the layout for this format:
class ApplicationController < ActionController::Base
before_action :add_html_to_template_lookup!, if: -> { request.format.template? }
layout :is_template_request?
private
def is_template_request?
request.format.template? ? false : "application"
end
# this will make rails fall back to rendering the "normal" html views
def add_html_to_template_lookup!
request.formats << Mime::Type.lookup("text/html")
end
end

image_tag not rendered from Code in Database

I have stored html code in a database field which is passed to the rails app.
<%= raw #exercise.explanation %>
The normal text is rendered correctly, it´s in the <p> .. </p>; but inside there the image codes are just displayed so output on the page is:
This is correct rendered text.
<%= image_tag ("exercises/picture.png"), style: 'height:auto; width:50%;' %>
Further text.
When I use <img src="exercises/picture.png"> or <img src="picture.png">inside the database entry, no picture is loaded either, just the broken image symbol of the browser.
Do you have the Assets Pipeline on? If you do, this could happen because of the generated hash that it put on your static assets to avoid cache problems. The thing is that the image_tag helper resolves this. It's a trade-off, but you could disable the Assets Pipeline and see if it works. To keep it on and do this, you will need a more elaborated solution.
You can try if it is that by disabling the assets digesting:
config.assets.digest = false
Alternatively you can have ERB interpret #exercise.explanation
<%= ERB.new(#exercise.explanation).result(binding) %>
This will take your #exercise.explanation and process it through ERB which appears to be what you are hoping for.
Caveat:
Be very careful what you allow to be stored in these "template" fields as things can go bad if you do not/can not sanitize this input. ERB#result is essentially a call to eval (which can be very dangerous)

Ruby on rails: convert text with html and rails code

Article in my app has field "body", which contains text with html. For example:
<div class ='skill_pic'>
<img src = "/assets/images/picture_1.png">
</div>
In view I call field "body" that:
<%= raw #article.body %>
In local machine all is ok, but when I deploy my app on production, images don't display right and browser console returns a 404 error.
image_tag in article body can solve my problem, I mean:
<div class ='skill_pic'>
<%= image_tag('images/picture_1.png') %>
</div>
But helper raw can't convert text with html and rails method
Now, I think in three directions:
find right path for images on production
find some helper, which can right convert text with html and rails code
find another solution
I suppose you want to do some kind of mini-CMS. Be careful not letting users fill in data in your database. You get really bad security problems. If user can edit your html, you better use some kind of templating engine like Liquid or markdown.
That being said, you should just not use the asset pipeline for the referenced images. put the images in the public folder instead of the assets folder. The public folder will be available like a web root '/', so without the 'public' in the url.
You could store erb partials like this in your database:
<div class ='skill_pic'>
<%= image_tag('images/picture_1.png') %>
</div>
And render them with ERB in your views:
<%= raw ERB.new(#article.body).result(binding) %>

Random CSRF token authenticity errors

I am getting intermittent CSRF token authenticity errors. Specifically, it occasionally happens when I submit a regular form via POST. I can get pass this error if I just go to a few other random pages before submitting the form again. This error does not always come up, it just comes up occasionally. It leads me to think that maybe the csrf meta tags being generated are not always valid.
I have already included the following statement in the header of application.html.erb
<%= csrf_meta_tags %>
I also have the following in application_controller.rb
protect_from_forgery
Is there anything else I should be doing?
If you're using the Rails helpers form_tag or form_for to generate your 'regular forms', then you will see if you inspect the HTML that an extra div is generated under the form tag, which contains a hidden field for utf8 compliancy, and an authenticity_token.
If you're writing your own forms (with <form>...</form> or %form) then you will need to manually add the authenticity token.
There's another helper called form_authenticity_token that you can use thus:
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>">
But I'd recommend you use the Rails form tag helpers, and avoid adding you own authenticity token fields.

output a variable in rails containing html code Ruby on Rails

I have a little problem with an output in ruby and rails.
I am still a beginner at rails, so it can be that the solution is pretty easy and i just can't see it.
I am trying to parse a website and put out some of the sourcecode on my own website.
Problem: it always puts out the whole source code as a text and is not interpreting the html code. how can i change that?
code:
page = Nokogiri::HTML(open("https://www.google.ch/search?client=ubuntu&channel=fs&q=google&ie=utf-8&oe=utf-8&redir_esc=&ei=WMpyUfSWEuz07AaTioCwDw"))
source = page.css('div#_css0')
<%= page %>
result:
http://postimg.org/image/dsaib9lx3/
I want to it to look like:
http://postimg.org/image/z9qlhoef5/
Thanks for any suggestions!
You should use raw in erb. It is actually equivalent to calling html_safe on it, but, just like h, is declared on a helper, so it can only be used on controllers and views.
page = Nokogiri::HTML(open("https://www.google.ch"))
<%= raw page %>
or
<%= raw Nokogiri::HTML(open("http://www.google.com")) %>
In Rails views every string content gets escaped, unless you use html_safe (docs)