Как волшебство урожая работает в ActionView?
Я смотрел на то, как работает content_for и наблюдал за block.call
в capture_erb_with_buffer
метод. Это очевидно волшебным образом записывает в буферную переменную, которая затем удаляется. Тем не менее, это я считаю устаревшим, и вы можете просто позвонить <%=yield :tag%>
сейчас. Как это работает? Если я называю yield из шаблона ERB, где это уступает?
Простой пример кода, чтобы проиллюстрировать это, был бы очень признателен.
3 ответа
Этот маленький крошечный метод называется execute
в ActionView::Base
все объясняет http://google.com/codesearch/p?hl=en#m8Vht-lU3vE/vendor/rails/actionpack/lib/action_view/base.rb&q=capture_helper.rb&d=5&l=337
def execute(template)
send(template.method, template.locals) do |*names|
instance_variable_get "@content_for_#{names.first || 'layout'}"
end
end
do |*names|... end
блок тот, кто получает yield
, Вы заметите, что @content_for_#{names.first}
совпадает с переменной, установленной в content_for
процесс.
Он вызывается из AV::TemplateHandlers::Compilable в #render, и я бы предположил и другие места.
def render(template)
@view.send :execute, template
end
Я не уверен как yield
функции на уровне ERB, но я знаю, как это работает применительно к макетам.
Вот пример файла layout.html.erb:
<html>
<head>
<title> <%= @title || 'Plain Title' %> </title>
<%= yield :head %>
</head>
<body>
<div id='menu'>
<%= yield :menu %>
</div>
<div id='content'>
<%= yield %>
</div>
<div id='footer'>
<%= yield :footer %>
</div>
</body>
Я определил 4 выхода (:head,:menu,:footer и default) и переменную экземпляра @title.
Теперь действия контроллера могут отображать эти слоты в эти места. Обратите внимание, что представление отображается перед макетом, поэтому я могу определить переменную типа @title в представлении и определить ее в макете.
Примеры просмотров: О странице
<% @title = 'About' %>
<% content_for :menu do %>
<%= link_to 'Back to Home', :action => :home %>
<% end %>
We rock!
<% content_for :footer do %>
An Illinois based company.
<% end %>
Страница редактирования
<% @title = 'Edit' %>
<% content_for :head do %>
<style type='text/css'> .edit_form div {display:inline-block;} </style>
<% end %>
<% form_for :thing, :html => {:class => 'edit_form'} do |f| %>
...
<% end %>
Вы можете смешивать и сопоставлять, какие данные вы хотите поместить в данные и что происходит в content_for :something
будет вставлен в соответствующий yield :something
в файле макета.
Это даже работает для частичных операций, частичное может вставлять свой собственный блок content_for: что-то, что будет добавлено с любыми другими вызовами content_for.
Просто:
Вызов yield в методе выполняет код, который был передан методу через блок.
Например
def my_method
yield
end
my_method { puts "Hello" }
my_method { puts "World" }
эти 5 строк приведут к следующему выводу на экран
Hello
World
Смотрите следующую страницу для хорошего обсуждения доходности в Ruby: Ruby Yield