yield in ERB without rails
I don't think you can - Rails provides that infrastructure as part of actionpack.
What you may be able to do is take actionpack and add it into your script.
Alternatively you could roll a lightweight templating system yourself.
Alternatively alternatively use Rails or Merb or Sinatra.
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
Rails: about yield
Without any arguments, yield will render the template of the current controller/action. So if you're on the cars/show
page, it will render views/cars/show.html.erb
.
When you pass yield an argument, it lets you define content in your templates that you want to be rendered outside of that template. For example, if your cars/show
page has a specific html snippet that you want to render in the footer, you could add the following to your show template and the car_general
layout:
show.html.erb:
<% content_for :footer do %>
This content will show up in the footer section
<% end %>
layouts/car_general.html.erb
<%= yield :footer %>
The Rails Guide has a good section on using yield and content_for: http://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield
The API documentation for content_for
is helpful too and has some other examples to follow. Note that it's for Rails 3.1.1 , but this functionality has not changed much since 2.3, if at all and should still apply for 3.0.x and 3.1.x.
Is it possible to evaluate a yield statement in an html.erb template using the ERB library?
You need to pass the block you want to context wherein you create the Binding
that you'll use with the template:
require 'erb'
def render(name)
TEMPLATE.result(binding)
end
render('evianpring') { 'blocks' }
# => "evianpring yields to the power of blocks!"
Let's dive into why this works. From the binding docs:
Objects of class Binding encapsulate the execution context at some
particular place in the code and retain this context for future use.
The variables, methods, value of self, and possibly an iterator block
that can be accessed in this context are all retained.
So what's available in execution context of the binding were creating here?
def render(name)
TEMPLATE.result(binding)
end
- Any variables local to
#render()
likename
- Any globals like
TEMPLATE
- Any block we pass to
#render()
Hence if we want to use yield will need to pass a block to #render()
Ruby erb templates with yield
This problem is independent of ERB and is because of the way yield
works. Yield expects to be called within the message body and expects a block to yield it. Let's take this example
# This is equivalent to
# def func
# ERB.new('<%= yield %>').result(binding)
# end
def test_print
yield
end
If we call the method without a block
irb(main):038:0> test_print
LocalJumpError: no block given (yield)
from (irb):36:in `test_print'
from (irb):38
from /Users/agupta/.rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'
irb(main):039:0>
If we call the method with block
irb(main):039:0> test_print { "hello world" }
=> "hello world"
irb(main):040:0>
In the latter case
ERB.new('<%= yield %>').result(binding) { 123 }
Your block is not being passed as yield
is outside the message body and you cannot do
irb(main):042:0> yield.tap { "hello world" }
LocalJumpError: no block given (yield)
from (irb):42
from /Users/agupta/.rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'
irb(main):043:0>
What does “yield” do?
It tells Rails to put your view content to this block (which is called by yield
) at that place in the layout file.
Checkout the rails guide to learn more about the ActionView.
https://guides.rubyonrails.org/action_view_overview.html
As pointed out by @Aleksei Matiushkin, yield
is pure ruby, so you should also learn more about that in your own time.
Here's a (my) visual presentation to explain what happened on that line:
view.html.erb:
<p>Hello there!</p>
<p>I'm a content from view</p>
layout.html.erb:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<%= yield %>
</body>
</html>
Now the results will be like this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>Hello there!</p>
<p>I'm a content from view</p>
</body>
</html>
Ruby method that yields one ERB template over another
I hope I got you question.
The following link should answer your question
How can I use views and layouts with Ruby and ERB (not Rails)?
Rails yield and content_for wieird behaviour, `yield :filter` only work if placed after default yield
Thanks everyone on reddit and @Ezhil i found a solution, this is what i did
what i did is i placed the content_for
capture group before the render like this
#index.html.erb
<% content_for :filters do %>
<h2> Content for Filters </h2>
<% end %>
<%= render 'layouts/sub_header' do %>
<h2> Content For Yield </h2>
<% end %>
and in my partial
#layouts/_subheader.html.erb
<div class="subheader">
<%= content_for :filters %>
<%= yield %>
</div>
It's because the block isn't executed until the first yield, so there's no content captured until that runs.
Related Topics
Rails Ssl Issue: (Https://Example.Com) Didn't Match Request.Base_Url (Http://Example.Com)
Ruby: How to Find Non-Unique Elements in Array and Print Each with Number of Occurrences
Synchronized Method for Concurrency in Ruby
Get Text Directly Inside a Tag in Nokogiri
Heroku - How to Write into "Tmp" Directory
Pg Error Could Not Connect to Server: Connection Refused Is the Server Running on Port 5432
Are Ruby 1.9 Regular Expressions Equally Powerful to a Context Free Grammar
"Errno::Eaccess...Permission Denied" Running Compass Watch
How to Get Ruby to Parse Time as If It Were in a Different Time Zone
Constants or Class Variables in Ruby
How to Remove Repeated Spaces in a String
How to Iterate Through an Array Starting from the Last Element? (Ruby)
Split Array into Sub-Arrays Based on Value
Using the Value of a Variable as Another Variables Name in Ruby