Include ERB delimiters inside of a string in an ERB block
If I'm understanding you right, your real problem is that heredocs behave like double quotes as far as interpolation is concerned. So all you need is a quoting mechanism that behaves like single quotes. Ruby has lots of string quoting mechanisms, in particular we have %q{...}
:
<% code = %q{
<div>
#{ image_tag 'image.png' }
</div>
} %>
You can use other delimiters if you'd like: %q|...|
, %q(...)
, etc. There's still a change of course but at least you don't have to worry about interpolation problems.
If you really want to use a heredoc, you can specify the heredoc terminator with quotes and the corresponding quoting style will apply to the content:
<% code = <<'PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR'
<div>
#{ image_tag 'image.png' }
</div>
PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%>
The single quotes in <<'PLACE...'
specify that single quoting rules (i.e. no interpolation) apply to the heredoc's content.
Of course none of that stuff will work with embedded ERB like this:
<% code = %q{
<div>
<% ... %>
</div>
} %>
because the ERB parser will see the first %>
as the closing delimiter for the outer <% code...
part. Fear not, I think I have a plan that will work without involving gross hacks or too much work.
Some preliminaries:
- Rails uses Erubis for ERB processing.
- Erubis allows you to change the delimiters with the
:pattern
option to its constructor. - Rails uses Tilt and Sprockets to handle the template processing pipeline, these allow you to make the right things happen to
pancakes.js.coffee.erb
in the right order.
Using the above you can add your own template format that is ERB with a different delimiter and you can have Rails use this new format to handle your "special" sections before the normal ERB processing can make a mess of things.
First you need to hook up Tilt. If you have a look at lib/tilt/erb.rb
in your Tilt installation, you'll see the Erubis stuff in Tilt::ErubisTemplate
at the bottom. You should be able to subclass Tilt::ErubisTemplate
and provide a prepare
override that adds, say, a :pattern => '<!--% %-->'
option and punts to the superclass. Then register this with Tilt and Sprockets in a Rails initializer with something like this:
Tilt.register(Your::Template::Subclass, 'klerb') # "kl" for "kludge" :)
Rails.application.assets.register_engine('.klerb', Your::Template::Subclass)
Now your application should be able to handle .klerb
files with <!--% ... %-->
as the template delimiters. And you can also chain your klerb with erb using names like pancakes.html.erb.klerb
and the file will go through klerb before the ERB; this means that templates like this (in a file called whatever.html.erb.klerb
):
<!--% code = <<PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
<div>
<% image_tag 'image.png' %>
</div>
PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%-->
<!--%= "code = escape_the_erb_as_needed(%q{#{code}})" %-->
<% do_normal_erb_stuff %>
will do The Right Thing.
You'd need a helper to implement the escape_the_erb_as_needed
functionality of course; a little experimentation should help you sort out what needs to be escape and in what way.
All that might look a bit complicated but it is really pretty straight forward. I've added custom template processing steps using Tilt and Sprockets and it turned out to be pretty simple in the end; figuring out which simple things to do took some work but I've already done that work for you:
Tilt::Template
subclass, you get this by piggy backing onTilt::ErubisTemplate
.- Register with Tilt by calling
Tilt.register
. - Register with Sprockets by calling
Rails.application.assets.register_engine
. - ...
- Profit.
erb: Using each_with_index on a link_to id string
Just regular ruby interpolation
id: "flag_#{i}"
How do I yield from an ERB code block without rendering it?
ERB has an internal buffer, which makes using blocks a bit more complicated, as you can see in your code example.
Rails provides a capture method, which allows you to capture a string inside this buffer and return it from a block.
So your helper would become the following:
def make_backwards
capture do
yield.reverse
end
end
ERB String interpolation generating incorrect HTML syntax
This produces:
<div class="product" fav>
No, it doesn't. It produces <div class=product fav>
. What you see (via something like "inspect element", correct?) is browser trying to interpret your broken markup as close to html spec as it can.
As noted in other answers, what you should do instead is something like this:
<div class="<%= cls %>">
Rendering ERB in models: no implicit conversion of ERB into String
The best and easiest way to do this is to use JQuery. First, put the ASCII map inside a div with id="ascii-map"
in your template. Then switch to the front-end. Once the DOM is fully loaded, you can parse the ASCII map, look for the asterisk, and then wrap it in a span element that has red color defined for its font.
In your CSS:
.red-font {
color: red;
}
Then, some JQuery:
$(document).ready(function() {
var text = $('#ascii-map').html();
var textWithRed = text.replace("*", "<span class='red-font'>*</span>");
$('#ascii-map').html(textWithRed);
});
I test this and confirmed that it works.
Error compiling ERB code from string
“Normal” Eruby doesn’t allow for expressions using <%=
to have blocks the way Rails uses them. Rails extends the Erubis Eruby handler to add support for them. Your test is just tring to use Erb directly, so this support isn’t available.
You need to make sure this support is loaded for this to work. I can get get it working with this:
ActionView::Template::Handlers::Erubis.new(template).evaluate(ActionView::Base.new)
I don’t know if this is the best way though. Check the RSpec docs, there may be a better way for testing parts of views like this.
Custom helper with block
Apparently, when using blocks, the equal sign has to be dropped. The following works:
<% wrap_me('span') do %>
Hello
<% end %>
Related Topics
How to Build Ruby 2.1.3 on Osx 10.10 Gm 3.0 with Rbenv
Git Bash Chcp Windows7 Encoding Issue
Can't Install Ruby via Rvm, Error Running '_Rvm_Make -J4' on Ubuntu 22.04
Insert Rows on Specific Line in a File
Ruby: "If !Object.Nil" or "If Object"
Ruby - What's the Difference Between Single and Double Quotes
Could Not Find Gem 'Logstash-Devutils (>= 0) Ruby' in Any of the Gem Sources
Ruby Net/Http Opening Connection Very Slow
Ruby - Return Byte Array Containing Two's Complement Representation of Bignum/Fixnum
How to Change Ruby to Version 1.9.3 (Again) with Rvm
Rails 7 Signup Form Doesn't Show Error Messages
Building a Simple Search Form in Rails
Ruby Outputting to the Same Line as the Previous Output
Rails: Pundit::Authorizationnotperformederror