【问题标题】:How does the yield magic work in ActionView?收益魔法在 ActionView 中是如何工作的?
【发布时间】:2011-02-07 12:09:35
【问题描述】:

我是looking at content_for 的工作原理,并在capture_erb_with_buffer 方法中观察了block.call。它显然神奇地写入缓冲区变量,然后将其修剪。但是,我认为这已被弃用,您现在可以致电 <%=yield :tag%>。这是如何运作的?如果我从 ERB 模板调用 yield 到哪里?

非常感谢提供一个简单的代码示例来说明这一点。

【问题讨论】:

    标签: ruby-on-rails actionview


    【解决方案1】:

    我不确定 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 个 yield(: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 :something 块,该块将与任何其他 content_for 调用一起添加。

    【讨论】:

      【解决方案2】:

      ActionView::Base 中称为 execute 的这个小方法解释了一切。 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 进程中设置的变量匹配。

      它是从#render 中的 AV::TemplateHandlers::Compilable 调用的,我假设其他地方也是如此。

        def render(template)
          @view.send :execute, template
        end
      

      http://google.com/codesearch/p?hl=en#m8Vht-lU3vE/vendor/rails/actionpack/lib/action_view/template_handlers/compilable.rb&q=execute&exact_package=git://github.com/payalgupta/todo-list.git&sa=N&cd=17&ct=rc&l=28

      【讨论】:

        【解决方案3】:

        简单地说:

        在方法中调用 yield 会执行通过块传递给方法的代码。

        例如

        def my_method
          yield
        end
        
        my_method { puts "Hello" }
        my_method { puts "World" }
        

        这 5 行将在屏幕上产生以下输出

        Hello
        World
        

        有关 Ruby 中产量的精彩讨论,请参阅以下页面:Ruby Yield

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 2019-09-19
          • 2010-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多