render_tree for Rails

Eric Hodel | Fri, 08 Sep 2006 18:02:00 GMT

Posted in , ,

Spelunking deep in unfamiliar Rails view code? Flushing out the cobwebs and updating your code? Don't know what gets rendered when?

I have a solution for you:

class ActionView::Base

  alias plain_render render

  RENDERS = [:partial, :template, :file, :action, :text, :inline, :nothing,
             :update]

  def render(*args)
    @level ||= 0

    print '  ' * @level

    case args.first
    when String then
      p args.first
    when Hash then
      hash = args.first
      found = hash.keys & RENDERS
      if found.length == 1 then
        puts "%p => %p" % [found.first, hash[found.first]]
      else
        raise "Dunno: %p" % [hash]
      end
    else
      raise "Dunno: %p" % [args]
    end

    @level += 1
    result = plain_render(*args)
    @level -= 1
    result
  end

end

Drop that in test/render_tree.rb and require it in your tests when you want to see a tree like this:

$ ruby test/views/things_view_test.rb -n test_view
Loaded suite test/views/things_view_test
Started
"things/things-header"
  "things/sidebar"
    "widgets/forms/goal_form"
    :partial => "widgets/sidenav_boxes/invite_and_edit"
      "widgets/sidenav_boxes/_invite_and_edit"
    :partial => "widgets/forms/edit_worth_doing_form"
      "widgets/forms/_edit_worth_doing_form"
    :partial => "widgets/sidenav_boxes/tags"
      "widgets/sidenav_boxes/_tags"
    :partial => "widgets/sidenav_boxes/popular_places"
      "widgets/sidenav_boxes/_popular_places"
    :partial => "widgets/sidenav_boxes/google_ads"
      "widgets/sidenav_boxes/_google_ads"
    :partial => "widgets/sidenav_boxes/find_help"
      "widgets/sidenav_boxes/_find_help"
    :partial => "widgets/sidenav_boxes/people_who_reached_this_goal"
      "widgets/sidenav_boxes/_people_who_reached_this_goal"
    :partial => "widgets/sidenav_boxes/quotation"
      "widgets/sidenav_boxes/_quotation"
    :partial => "widgets/sidenav_boxes/goal_created_by"
      "widgets/sidenav_boxes/_goal_created_by"
"widgets/general/post_add_messages"
"things/shared_body"
  :partial => "widgets/goals_gallery_teaser"
    "widgets/_goals_gallery_teaser"
  :partial => "entries_bucket"
    "things/_entries_bucket"
  "widgets/forms/related_goals"
.
Finished in 1.205494 seconds.

1 tests, 7 assertions, 0 failures, 0 errors

(I think I'll end up throwing this into ZenTest.) 4 comments

Comments RSS FEED

Very nice—trying it out now. Thanks!

Chris said about 2 hours later

If you add it to ZenTest, how about making it into an assertion? Something like matching a structural regular expression on renderings

  assert_render_tree ['root_template',
    { :partial => 'child1', :count => 3 },
    [ { :partial => 'child2' }, <grand_children> ],
    <more_children>],
    render_something

Don’t make me write a BNF for it…

Michael Schuerig said 2 days later

@Michael: I’m certainly not going to write it, sounds too complicated to me. :) I’ll just add it as a debugging tool.

Eric Hodel said 2 days later

I’m entirely happy if you just do the assertion :-}

Michael Schuerig said 3 days later

Comments are disabled