How can an rspec test for a view pass if there is no action for the view in the controller?

The rspec test looks like this:

require 'spec_helper'

describe "Static pages" do

  describe "Home page" do

    it "should have the h1 'Sample App'" do
      visit '/static_pages/home'
      page.should have_selector('h1', :text => 'Sample App')
    end

  end

end

My controller looks like this:

class StaticPagesController < ApplicationController
end

If you go to that url in the browser does it show a page with the header?

Is there a page in public/static_pages that matches that url? In
which case that will be served without the need for a controller
action.

What does test.log show when you run the test?

Colin

1) Yes, the page shows when I start rails server, and then use the url:

http://localhost:300/static_pages/home

2) Everything in public/ was created by rails new:

$ ls public/
404.html 500.html index.html
422.html favicon.ico robots.txt

3) test.log:

Started GET "/static_pages/home" for 127.0.0.1 at 2012-08-31 10:04:28
-0700
Processing by StaticPagesController#home as HTML
  Rendered static_pages/home.html.erb within layouts/application (3.7ms)
Completed 200 OK in 21ms (Views: 20.0ms | ActiveRecord: 0.0ms)
  [1m[35m (0.1ms)[0m rollback transaction
  [1m[36m (0.1ms)[0m [1mbegin transaction[0m

Started GET "/static_pages/home" for 127.0.0.1 at 2012-08-31 10:04:28
-0700
Processing by StaticPagesController#home as HTML
Completed 200 OK in 2ms (Views: 1.6ms | ActiveRecord: 0.0ms)
  [1m[35m (0.1ms)[0m rollback transaction
  [1m[36m (0.1ms)[0m [1mbegin transaction[0m

Yet here is my controller:

class StaticPagesController < ApplicationController
end

Previously, I had actions in my controller, but I wanted to see if the
tests would fail without the actions, and I fully expected them to fail,
but they won't. I have everything at github:

https://github.com/7stud/sample_app25

Curiously, if I write a test for a non-existent view, I get three
errors: First, no route; then after I add the route:

get '/static_pages/something'

I get an error saying there's no action; then after I add the action, I
get an error saying there's no view; then after adding a view, the test
passes. Subsequently, if I delete the action for that view, the test
still passes. Why?

What's in your routes.rb? This could be a catch-all route firing. In Ryan Bates' Railscast on semi-static pages, he mentions that a completely empty controller will work as long as there is a properly named view file at the expected path. I tried it in a quick test app, but it didn't work in vanilla 3.2.

Walter

Thanks for the response. Here is my routes.rb:

SampleApp25::Application.routes.draw do
  get "static_pages/home"
  get "static_pages/help"
  get "static_pages/about"
  get "static_pages/contact"

  # The priority is based upon order of creation:
  # first created -> highest priority.

  # Sample of regular route:
  # match 'products/:id' => 'catalog#view'
  # Keep in mind you can assign values other than :controller and
:action

  # Sample of named route:
  # match 'products/:id/purchase' => 'catalog#purchase', :as =>
:purchase
  # This route can be invoked with purchase_url(:id => product.id)

  # Sample resource route (maps HTTP verbs to controller actions
automatically):
  # resources :products

  # Sample resource route with options:
  # resources :products do
  # member do
  # get 'short'
  # post 'toggle'
  # end

Yup. I can confirm that with a similar route here in an otherwise entirely empty controller and a matching view in the correct folder, this just works without any logic at all. Let's hear it for convention over configuration!

Walter

So this is a route "problem"?

It's a feature of Rails. It's a problem if it causes problems. With the sort of routing you have, it's only going to expose the views you indicate in your routes.rb file. If you had a more liberal route like

match 'info/:action' => 'info#action'

then it would show any action.html you placed in the views/info folder, as long as it was requested properly.

Walter

It's a feature of Rails. It's a problem if it causes problems.

(Note: nothing in this post has anything to do with rspec.)

For me, that routing behavior is causing problems. Here's why: if I add
a route such as:

get "static_pages/dog"

...and then enter the url http://localhost:3000/static_pages/dog in my
browser, rails complains that there's no action called dog in the
StaticPagesController:

===

Unknown action

The action ‘dog’ could not be found for StaticPagesController

===

Then if I add the dog action to the controller, then create a view,
everything works fine and dandy.

You can skip the adding an action bit and go straight to creating a view

But if I then delete the dog action, and then use the same url,
http://localhost:3000/static_pages/dog, in my browser, this time I get a
different result–instead of getting an error the view displays. For
me, that inconsistent behavior is not right, and it should not be that
way. So I want to know whether there were reasons for the rails team
to institute that inconsistent behavior, or whether it is a bug.

This is a long standing rails feature (right back to 1.x at least): rails doesn’t make you define an empty action. I don’t think it’s a feature that gets a whole lot of use, but it’s definitely intentional (documented here: http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-by-default-convention-over-configuration-in-action )

Fred

Thanks for the response Frederick Cheung.

I don't like this 'default rendering', nor the misleading error message
saying the action is missing--but I guess I'll have to live with it. A
route and view is all that's necessary to render a page.

It is not inconsistent. You started with no action and no view and
url fails. You added action and view and url works. You deleted only
the action and the view continues to work. If you delete the view
then it will fail again. Perfectly consistent. In fact the empty
action is just not needed. Rails assumes that since you have provided
a route and a view that you would like them to work and saves you the
effort of providing an empty action. I never intentionally rely on
that myself as I find it a little confusing, but it is not
inconsistent.

Colin

It is not inconsistent.

Okay, perhaps it's more correct to say that Rails is flat out wrong.
Rails complains that I need an action when there isn't one, which is
false.

It is not inconsistent.

Okay, perhaps it's more correct to say that Rails is flat out wrong.
Rails complains that I need an action when there isn't one, which is
false.

What do you mean it complains that you need an action? I thought your
problem was that it did /not/ complain that there is no action in the
model.

Colin

If you don't even know what the posts in this thread say, why bother
posting anything?

I couldn't agree more.

Colin