Read more

Spec "content_for" calls in helpers

Arne Hartherz
March 05, 2012Software engineer at makandra GmbH

This only applies to RSpec below version 1.3.2. The issue has been fixed in RSpec 1.3.2, and most likely RSpec 2 and later versions.


Illustration money motivation

Opscomplete powered by makandra brand

Save money by migrating from AWS to our fully managed hosting in Germany.

  • Trusted by over 100 customers
  • Ready to use with Ruby, Node.js, PHP
  • Proactive management by operations experts
Read more Show archive.org snapshot

When you have a helper that calls content_for and want to check its behavior you should probably write a feature instead. If you still want to do it, mind the following.

Consider this helper:

module LayoutHelper
  def title(string)
    content_for :title, string
    string
  end
end

Somewhere in the layout we'd then say something like this: <title><%= yield :title %></title>.

Inspecting prepared content for content_for

If you want to inspect what the helper prepared for the view, you need to hack a bit:

it 'should work'
  helper.title('Hello Universe')
  helper.instance_variable_get('@content_for_title').should == 'Hello Universe'
end

Unfortunately, this may only work once. RSpec instanciates the helper object only once, thus keeping instance variables -- and since content_for always attaches, any second spec will break looking at @content_for_title.

Checking this more than once

When your application is up, you will actually get a fresh helper attached to the view each time your content is being rendered. We want something similar, so we define our own helper object:

let :helper do
  Spec::Rails::Example::HelperExampleGroup::HelperObject.new.tap do |helper|
    helper.send :extend, LayoutHelper
  end
end

it 'should work'
  helper.title('Hello Universe')
  helper.instance_variable_get('@content_for_title').should == 'Hello Universe'
end

it 'should still work'
  helper.title('Hello World')
  helper.instance_variable_get('@content_for_title').should == 'Hello World'
end

This applies to Rails 2. Maybe RSpec 2 / Rails 3 are smarter.

Posted by Arne Hartherz to makandra dev (2012-03-05 16:36)