Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdickey/a1b26dfa88922bd7082e to your computer and use it in GitHub Desktop.
Save jdickey/a1b26dfa88922bd7082e to your computer and use it in GitHub Desktop.
Slim and RSpec: I Was Obviously Doing It Wrong

Solved with the gracious help of @jenrzzz on IRC (whom I presume is the same as @jenrzzz on Twitter?

The solution was to change

    @blog = OpenStruct.new(title: blog_title,
                           subtitle: blog_subtitle,
                           entries: [])

to

    view.assigns[:blog] = OpenStruct.new(title: blog_title,
                           subtitle: blog_subtitle,
                           entries: [])

The former had Just Worked when dealing with this template as Haml in an earlier incarnation of the project. Changing to Slim, however, made my (implicitly) assigned variables go floating off into the void, never to return. Explicitly using view.assigns[:var_name] works both ways.

If someone can point me to where this charlie-fox is documented somehow, I'd be very appreciative. Until then, it may be runes and incantations, but as long as it's working, repeatable runes and incantations, I'm good to go... to bed, at this point.

Original content follows.


Trying to move to Slim from Haml in a Rails app, but having incredibly n00b problems that have stumped me all day long.

How the heck do I access object methods or fields in a Slim template? And how come this isn't blindingly obvious?

View spec and view template given below, as well as a transcript of a Pry session.

What am I missing here? I know it's trivial, but I'm just not seeing it. Any help greatly appreciated. Thanks.

A Blow-by-Blow of the Transcript

  1. We drop into the Pry debugger in our outermost :before block, just before the view is rendered. This allows us to examine the data that's been set (in @blog) and set a breakpoint in the ActionView::TestCase#reender code just before the actual rendering is done.
  2. We set the breakpoint, and then
  3. exit the current breakpoint, allowing RSpec to run until the next breakpoint is hit.
  4. We hit the breakpoint we just set, and look at the object that's been copied into the view assigns.
  5. Just to be blindingly obvious, we verify that accessing the blog title via a nested array works...
  6. ...as does a method call.
  7. We call view#render, just as it will be immediately after we exit the current breakpoint. We notice that the <h1> and <h2> tag pairs have empty content; our title and subtitle were not read by the template engine.
  8. We exit again, and the spec fails (as we now expect).

Again, why?

div class='page-header row'
/ Neither of these work. Neither does, e.g., `h2 = @blog.subtitle`
h1 = assigns[:blog][:title]
h2 = blog.subtitle
div class='page-content'
div class='row well'
p Find me in app/views/blog/index.slim
require 'spec_helper'
describe 'blog/blog/index.slim' do
before :each do
blog_title = 'Watching Paint Dry'
blog_subtitle = 'The trusted source for drying paint news and opinion'
@blog = OpenStruct.new(title: blog_title,
subtitle: blog_subtitle,
entries: [])
binding.pry
render
end
describe 'has the correct structure, including' do
before :each do
@rows = assert_select 'div.row'
end
it 'two "row" divs' do
expect(@rows).to have(2).items
end
describe 'a page-header row' do
it 'as the first row' do
header_row = assert_select 'div.page-header.row'
expect(header_row).to have(1).item
expect(header_row.first).to eq @rows.first
end
it 'containing the correct top-level header' do
assert_select @rows.first, 'h1', text: @blog.title, count: 1
end
end # describe 'a page-header row'
# ...
end # describe 'has the correct structure, including'
# ...
end
[jeffdickey@Jeffs-Prolog-iMac interactor_demo (mutator-2)]$ rspec spec/views/blog/blog/index.slim_spec.rb:33
Run options: include {:locations=>{"./spec/views/blog/blog/index.slim_spec.rb"=>[33]}}
Frame number: 0/23
From: /Users/jeffdickey/src/rails/meldd/interactor_demo/spec/views/blog/blog/index.slim_spec.rb @ line 11 :
6: blog_title = 'Watching Paint Dry'
7: blog_subtitle = 'The trusted source for drying paint news and opinion'
8: @blog = OpenStruct.new(title: blog_title,
9: subtitle: blog_subtitle,
10: entries: [])
=> 11: binding.pry
12: render
13: end
14:
15: describe 'has the correct structure, including' do
16:
[1] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> break vendor/ruby/2.0.0/gems/actionpack-3.2.17/lib/action_view/test_case.rb:115
Breakpoint 1: /Users/jeffdickey/src/rails/meldd/interactor_demo/vendor/ruby/2.0.0/gems/actionpack-3.2.17/lib/action_view/test_case.rb @ line 115 (Enabled) :
112:
113: def render(options = {}, local_assigns = {}, &block)
114: view.assign(view_assigns)
=> 115: @rendered << output = view.render(options, local_assigns, &block)
116: output
117: end
118:
[2] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> exit
Breakpoint 1. First hit.
From: /Users/jeffdickey/src/rails/meldd/interactor_demo/vendor/ruby/2.0.0/gems/actionpack-3.2.17/lib/action_view/test_case.rb @ line 115 ActionView::TestCase::Behavior#render:
113: def render(options = {}, local_assigns = {}, &block)
114: view.assign(view_assigns)
=> 115: @rendered << output = view.render(options, local_assigns, &block)
116: output
117: end
[3] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> view.assigns[:blog]
=> #<OpenStruct title="Watching Paint Dry", subtitle="The trusted source for drying paint news and opinion", entries=[]>
[4] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> view.assigns[:blog][:title]
=> "Watching Paint Dry"
[5] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> view.assigns[:blog].title
=> "Watching Paint Dry"
[6] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> view.render(options, local_assigns, &block)
=> "<div class=\"page-header row\"><h1></h1><h2></h2></div><div class=\"page-content\"><div class=\"row well\"><p>Find me in app/views/blog/index.slim</p></div></div>"
[7] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1>)> exit
F
Failures:
1) blog/blog/index.slim has the correct structure, including a page-header row containing the correct top-level header
Failure/Error: assert_select @rows.first, 'h1', text: @blog.title, count: 1
MiniTest::Assertion:
<"Watching Paint Dry"> expected but was
<"">.
# ./spec/views/blog/blog/index.slim_spec.rb:34:in `block (4 levels) in <top (required)>'
Finished in 1 minute 21.99 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/views/blog/blog/index.slim_spec.rb:33 # blog/blog/index.slim has the correct structure, including a page-header row containing the correct top-level header
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment