Testing views of nested resources

I’ve searched and searched, and just can’t find an answer on the list or
elsewhere. Forgive me if I’m missing something…

I’ve got the following bits of code:

app/controllers/widget_layouts_controller.rb:

class WidgetLayoutsController < ApplicationController
def new
@widget = Widget.find(params[:widget_id])
@widget_layout = WidgetLayout.new
end
end

app/models/widget_layout.rb:

class WidgetLayout < ActiveRecord::Base
belongs_to :widget
end

app/models/widget.rb:

class Widget < ActiveRecord::Base
has_one :widget_layout, :dependent => :destroy
end

From config/routes.rb:

resources :widgets do
resource :widget_layout
end

spec/widget_layouts/new.html_spec.rb:

require “spec_helper”

describe “widget_layouts/new.html.erb” do
it “should render the new widget layout form” do
widget = stub_model(Widget)
assign(params[:widget_id], widget)
render
rendered.should have_selector(“form”, :method => “post”, :action =>
widget_widget_layout_path(widget))
end
end

app/views/widget_layouts/new.html.erb

<%= form_for @widget_layout, :url => widget_widget_layout_path(@widget)
do |f| %>
<%= f.submit “Submit Widget Layout Information” %>
<% end %>

Here’s the error I get when running that spec:

widget_layouts/new.html.erb
should render the new widget layout form (FAILED - 1)

Failures:

  1. widget_layouts/new.html.erb should render the new widget layout
    form
    Failure/Error: render
    No route matches {:controller=>“widget_layouts”,
    :action=>“destroy”}

/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/route_set.rb:398:in
generate' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/route_set.rb:450:ingenerate’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/route_set.rb:478:in
url_for' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/url_for.rb:132:inurl_for’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/helpers/url_helper.rb:99:in
url_for' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/route_set.rb:195:inwidget_widget_layout_path’
# ./app/views/widget_layouts/new.html.erb:1:in
_app_views_widget_layouts_new_html_erb___4529585855698402853_2170042420_599441616533773267' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/template.rb:135:inblock in render’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications.rb:52:in
block in instrument' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications/instrumenter.rb:21:ininstrument’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications.rb:52:in
instrument' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/template.rb:127:inrender’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/render/rendering.rb:59:in
block in _render_template' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications.rb:52:inblock in instrument’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications/instrumenter.rb:21:in
instrument' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/activesupport-3.0.0.rc/lib/active_support/notifications.rb:52:ininstrument’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/render/rendering.rb:56:in
_render_template' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/render/rendering.rb:26:inrender’
#
/Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/test_case.rb:103:in
render' # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/rspec-rails-2.0.0.beta.20/lib/rspec/rails/example/view_example_group.rb:70:inrender’
# ./spec/views/widget_layouts/new.html_spec.rb:7:in `block (2
levels) in <top (required)>’

I believe this is because params[:widget_id] isn’t assigned when I’m
rendering new.html.erb. I know that’s an improper usage of #assign up
there, but this is what I was trying to rectify (obviously
incorrectly…) I’m confused as to how to mock/stub and specify parent
resource(s) when trying to test views of children resources. What
should I be doing differently?

Also–not an RSpec question–that’s the only way I can get that
#form_for call to work correctly. Everywhere I looked, it seemed that I
could simply use:

form_for [@widget, @widget_layout] do |f| %>

but alas, all I get is the following errors:


NoMethodError in Widget_layouts#new
Showing
/Users/brennon/Documents/Programming/checkouts/rails_projects/stan/app/views/widget_layouts/new.html.erb
where line #1 raised:

undefined method `widget_widget_layouts_path’ for
#<#Class:0x00000102c44ed0:0x00000102c3fa48>
Extracted source (around line #1):
1: <%= form_for [@widget, @widget_layout] do |f| %>
2: <%= f.submit “Submit Widget Layout Information” %>
3: <% end %>


Any chance I might get some help on this one while I’m at it? :slight_smile:
Many thanks,
Brennon B.
Software Researcher
Dundalk Institute of Technology
[email protected]
Ph.D. Researcher & Composer - Sonic Arts Research Centre
Queen’s University, Belfast
[email protected] / [email protected]

On 8 Sep 2010, at 16:20, Brennon B. wrote:

end

widget = stub_model(Widget)

 # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_dispatch/routing/route_set.rb:450:in `generate'
 # /Users/brennon/.rvm/gems/ruby-1.9.2-p0@stan/gems/actionpack-3.0.0.rc/lib/action_view/render/rendering.rb:59:in `block in _render_template'

Extracted source (around line #1):
1: <%= form_for [@widget, @widget_layout] do |f| %>
2: <%= f.submit “Submit Widget Layout Information” %>
3: <% end %>


Any chance I might get some help on this one while I’m at it? :slight_smile:
Well, that was certainly a stupid mistake…figured it out with this:

it “should render the new widget layout form” do
widget = stub_model(Widget, :id => “1”)
assign(:widget, widget)
params[:widget_id] = widget.id
assign(:widget_layout, mock_model(WidgetLayout).as_null_object)
render
rendered.should have_selector(“form”, :method => “post”, :action =>
widget_widget_layout_path(widget))
end

Now, can anyone provide some insight on a more elegant #form_for call
for me?

Thanks again,
Brennon