Rails中yield与content_for异常:yield :filters仅在默认yield后生效?
这确实是Rails的正常行为,我来帮你理清楚原因和解决办法
首先,问题核心在于**content_for的执行时机**:当你把content_for :filters写在局部视图的渲染块里时,这段代码只有在默认的yield被执行的时候才会运行。也就是说:
- 当你先调用
yield :filters再调用默认yield时,content_for :filters还没被执行,Rails还没存储这个区块的内容,自然输出为空; - 而当你先调用默认
yield时,块里的content_for :filters会被执行,内容被存储起来,之后的yield :filters就能正确输出内容了。
哪怕你换成<%= content_for :filters %>也没用,因为本质上yield :xxx和content_for :xxx(不带块)都是读取已存储的内容,前提是content_for :xxx的块已经被执行过。
解决办法有两种,看你更偏好哪种:
方法1:把content_for :filters移到渲染块外面
直接在调用局部视图之前先执行content_for :filters,这样无论局部视图里的yield顺序如何,内容都已经被存储好了:
<% content_for :filters do %> <h2> Content for Filters </h2> <% end %> <%= render 'layouts/sub_header' do %> <h2> Content For Yield </h2> <% end %>
方法2:在局部视图里先捕获默认yield的内容
通过capture方法先执行默认yield的内容(这样里面的content_for会被触发),再按你想要的顺序输出:
# layouts/_subheader.html.erb <div class="subheader"> <%# 先捕获默认yield的内容,触发里面的content_for %> <% default_content = capture { yield } %> <%= yield :filters %> <%= default_content %> </div>
这样即使content_for :filters写在默认yield的块里,也能确保它先被执行,之后yield :filters就能拿到内容了。
内容的提问来源于stack exchange,提问作者Nijeesh Joshy
相关产品推荐
相关产品推荐

