Rails 检查是否在 content_for 中定义了屈服: area

我想做一个条件渲染在布局级别的基础上,实际模板已经定义了 content_for(:an__area),有什么办法可以做到这一点吗?

36881 次浏览

Ok I am going to shamelessly do a self reply as no one has answered and I have already found the answer :) Define this as a helper method either in application_helper.rb or anywhere you found convenient.

  def content_defined?(symbol)
content_var_name="@content_for_" +
if symbol.kind_of? Symbol
symbol.to_s
elsif symbol.kind_of? String
symbol
else
raise "Parameter symbol must be string or symbol"
end


!instance_variable_get(content_var_name).nil?


end

Can create a helper:

def content_defined?(var)
content_var_name="@content_for_#{var}"
!instance_variable_get(content_var_name).nil?
end

And use this in your layout:

<% if content_defined?(:an__area) %>
<h1>An area is defined: <%= yield :an__area %></h1>
<% end %>

not really necessary to create a helper method:

<% if @content_for_sidebar %>
<div id="sidebar">
<%= yield :sidebar %>
</div>
<% end %>

then of course in your view:

<% content_for :sidebar do %>
...
<% end %>

I use this all the time to conditionally go between a one column and two column layout

I'm not sure of the performance implications of calling yield twice, but this will do regardless of the internal implementation of yield (@content_for_xyz is deprecated) and without any extra code or helper methods:

<% if yield :sidebar %>
<div id="sidebar">
<%= yield :sidebar %>
</div>
<% end %>

@content_for_whatever is deprecated. Use content_for? instead, like this:

<% if content_for?(:whatever) %>
<div><%= yield(:whatever) %></div>
<% end %>
<%if content_for?(:content)%>
<%= yield(:content) %>
<%end%>

I use @view_flow and value of the content method before checking if the content is present in the view like this:

@view_flow.content[:header_left_or_whatever_the_name_of_your_block_is].present?

Recently stumbled upon it when showing all local, global and instance variables of self in the console with byebug. I’m a fan using this because it’s straight from Rails, won’t throw an error, won’t hide anything w “Rails magic”, returns a definite true or false, + only checks the content in the current context of the view being rendered.

@view_flow is an instance attribute of ActionView::Context and because Action View contexts are supplied to Action Controller to render a template it will be available to any view that has been rendered by Rails. Although it checks for content, the content_for block will not be yielded if it isn’t there. So it’s been my perfect solution in similar situations.