views:

123

answers:

4

Hello Railers,

I have a simple yield use case and for some unknown reason the default case is never shown:

In my super_admin layout I have:

<%= yield :body_id || 'super_admin_main' %>

My controller

class Superadmin::GolfsController < ApplicationController
  layout "super_admin"

  def show 

  end
end

My show view

With or without

<% content_for(:body_id) do %>sadmin_golfs<% end %>

With: sadmin_golfs is shown.

without: empty string is shown instead of super_admin_main

Can anyone reproduce the same behavior ?

Rails 3

+7  A: 

Use parentheses:

<%= (yield :body_id) || 'super_admin_main' %>

Or

<%= yield(:body_id) || 'super_admin_main' %>

Without them it is assuming yield (:body_id || 'super_admin_main')

EDIT: Rails 3 uses ActiveSupport::SafeBuffer instead of string/nil (Rails 2), so the output is not nil even if there is no content_for provided. So try:

<%= yield(:body_id).empty? ? 'super_admin_main' : yield(:body_id)%>
Voyta
Actualy it stills shows an empty string when no content_for is supplied.
coulix
You do not suppy `content_for` at all or it is just blank like `<% content_for(:body_id) do %> <% end %>` ?
Voyta
See edited answer
Voyta
A: 

In rails 3

<%= yield(:body_id).present || 'super_admin_main' %>

raises undefined method `present'

coulix
+2  A: 

Why no test if there are a content_for or not define in view compilation.

In the content_for code we can see :

def content_for(name, content = nil, &block)
  ivar = "@content_for_#{name}"
  content = capture(&block) if block_given?
  instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}".html_safe)
  nil
end

So in your case, the @content_for_body_id is define if a content_for is in your view.

You can made :

<%=  instance_variable_defined?('@content_for_body_id') ? yield(:body_id) : 'super_admin_main' %>

If you prefere you can generate an helper after

def yield_or(part, result)
  instance_variable_defined?("@content_for_#{part}") ? instance_variable_get("@content_for_#{part}") : result
end

and call it in your view by

<%= yield_or(:body_id, 'super_admin_main') %>

It's works only with Rails 2.3.x

In Rails 3 :

there are this method content_for?

shingara
A: 

try <%= yield(:title).presence || 'My Default Title' %>

Object#presence "is equivalent to object.present? ? object : nil" (AS 3 rc docs), and essentially allows the traditional syntax with the titles