How do I html_escape text data in a sinatra app? - ruby

I have a small Sinatra app which generates html fragments for me from an ERB template.
How do I html_escape the output?
The <%=h somestring %> helper does not exist in Sinatra.

Rack::Utils includes a HTML escape method. http://www.sinatrarb.com/faq.html#escape_html

require 'CGI'
get '/html' do
erb :view
end
def h(html)
CGI.escapeHTML html
end
__END__
##view
<% File.open('my.html') do |f| %>
<%=h f.read() %>
<% end %>

Related

Ruby: capture and reuse block of HTML code in ERB template

Note that I cannot use Rails or Javascript.
Is there any way to repeat a block of HTML code using only Ruby / ERB?
In Rails I would do this:
<% content_for :mycontent do %>
some html code
that I want to capture
etc
<% end %>
Then, here, in the same template, I can reuse the block...
<%= content_for :mycontent %>
Multiple times...
<%= content_for :mycontent %>
Is there any equivalent without Rails?

How to render a value from an .rb file into an .erb file

I don't have much experience with Ruby all I wan't to do is render a value that I declare in an .rb file in an .erb file.
In my .rb file I have this:
def abc()
begin
"aaaaa"
end
end
In my .erb file I have this:
Hello <% abc %>
When I run the app I only see:
Hello
But I expect to see:
Hello aaaa
Anybody can give me a hand, I don't really know ruby at all. Also I have no idea if this is ruby or ruby on rails so sorry if the tag below is wrong.
In Sinatra, register your method as a helper in .rb file:
helpers do
def abc
"aaaaa"
end
end
Omit parentheses if your methods don't need arguments. Also, begin/end block isn't necessary here.
You can call your helper in .erb template:
<%= abc %>
Don't forget = in the opening tag.
http://sinatrarb.com/intro.html section 'Helpers'.
It's unclear what you want to achieve. But If you just want some text in your erb you can do something like this:
erb :myerb, locals: {text: "aaaaa", saved: false}
myerb.erb
<% if saved %>
Hello <%= text %>
<% endif %>
This would also work for functions.
First of all, you need to be aware that a defined method inherently includes the functionality of a begin/end block so you donĀ“t need to put them again. Assuming you are using sinatra, here is what I think you need:
my.rb
require 'sinatra'
def abc
"aaaa"
end
get '/' do
erb :my, locals: {variable: abc}
end
my.erb
<html>
<body>
<p>
Hello <%= variable %>
</p>
</body>
</html>
Run ruby my.rb and then open http://localhost:4567/

Ruby Iterate from an object using ERB

I'm new, was tasked to do a front end job but I thought i can figure out ERB easily.
In my app.rb
variables defined
def find_listings
3.times.map { random_item }
end
def random_item
{
name: 'blah',
location: 'LA'
}
end
get '/' do
#listings = find_listings
erb :index
end
In my ERB file I am trying to iterate
index.erb
<% #listings.each do |value | %>
<strong><%= value %><br/>
<%# This returns {:name=>"blah", :location=>"New York"} %>
<strong><%= value['name']%></strong><br/>
<%# This returns nothing %>
<% end %>
How do i get the name value?
Your hash has symbols as keys (not strings), so you can access name this way: value[:name].

Proc inside ERB

There's something weird going on here that I can not understand when I try to implement multiple content_for blocks in ERB using plain Ruby.
Here is my code:
# helper.rb
require 'erb'
def render(path)
ERB.new(File.read(path)).result(binding)
end
def content_for(key, &block)
content_blocks[key.to_sym] = block
end
def yield_content(key)
content_blocks[key.to_sym].call
end
def content_blocks
#content_blocks ||= Hash.new
end
And template:
<% #test.html.erb %>
<% content_for :style do %>
style
<% end %>
<% content_for :body do %>
body
<% end %>
<% content_for :script do %>
script
<% end %>
When I open irb to test, I get
irb(main):001:0> require './helper'
=> true
irb(main):002:0> render 'test.html.erb'
=> "\n\n\n"
irb(main):003:0> content_blocks
=> {:style=>#<Proc:0x005645a6de2b18#(erb):2>, :body=>#<Proc:0x005645a6de2aa0#(erb):5>, :script=>#<Proc:0x005645a6de2a28#(erb):8>}
irb(main):004:0> yield_content :script
=> "\n\n\n\n script\n"
irb(main):005:0> yield_content :style
=> "\n\n\n\n script\n\n style\n"
Why yield_content :script got the \n\n\n prepended and why yield_content :style got the script\n\n in result.
If you do
ERB.new(File.read(path)).src
Then you can see what erb compiles your template to. The template ends up looking like (formatted for readability)
_erbout = ''
_erbout.concat "\n"
#test.html.erb
_erbout.concat "\n"
content_for :style do
_erbout.concat "\n style\n"
end
Where _erbout is the buffer that accumulates the output from your template. _erbout is just a local variable,m
When you call your procs they are all just appending to that same buffer, which already contains the result from the template render.

How to extend ERB templating

I would like to extend ERB so every output tag - <%= %> - content is pre-processed before the result is rendered.
For example,
<%= 'test' %>
should now render
!test!
instead of
test
How can I do this ?
Something like this? (untested)
require 'erb'
template = File.read(template_file)
template.gsub!(/<%=(.*?)%>/, '!\1!')
erb = ERB.new(template)
result = erb.result
There is no straightforward way to do that. Perhaps you can define:
class String; def bang; "!#{self}!" end end
and do
<%= "test".bang %>

Resources