开发者

Simple Rails routing problem

I am having another ruby nuby moment and can't seem to wrap my head around this simple problem.

I have this as a route:

resources :pages

I have this in my pages controller:

def testy

end

and I have this in app/views/pages/testy.html.erb

<h1>Testy</h1>

I am trying to access the page like so: http://localhost:3000/pages/testy

And I get the following error:

Couldn't find Page with ID=testy

Here is the log:

Started GET "/pages/testy" for 127.0.0.1 at Thu Dec 09 14:24:51 -0600 2010
Processing by PagesController#show as HTML
Parameters: {"id"=>"testy"}
[1m[35mPage Load (0.3ms)[0m  SELECT "pages".* FROM "pages" WHERE ("pages"."id" = 0) LIMIT 1
Completed   in 12ms

ActiveRecord::RecordNotFound (Couldn't find Page with ID=testy):
app/controllers/pages_controller.rb:11:in `show'

It's obvious by the log that it's trying to access #show, but why? I think it's a problem with my route. Can some开发者_StackOverflow社区one give me a quick pointer?

I was following the Rails Guides here and I think this is what is throwing me off "... the rule is that if you do not explicitly render something by the end of the controller action, rails will look for the action_name.html.erb template in the controllers view path and then render that, ..."


When you set up a RESTful route like resources :pages, by default anything after pages/ in the URL is put into the params hash as an ID so pages/1 would give you a params hash that includes {:id => '1'} (among other things like :controller, :action, etc.).

There is an exception for certain actions like pages/new or pages/edit . Rails is smart enough to know that 'new' and 'edit' are not IDs. You just need to tell rails that 'testy' is not an ID either.

You can define custom actions using member or collection inside a block attached to resources like this:

resources :pages do
  collection do
    get :testy  # will match pages/testy
    get :foo
    post :bar
  end

  member do
    get :baz # will match pages/1/baz
  end
end

Now rails will know that pages/testy is a custom route and will not interpret 'testy' as an ID. Make sure your route names are never the same as your ID. In other words, if you had a Page that had an id of testy for some reason, you'd never be able to reach it given the above routes!

For deeper knowledge, I highly recommend the official rails guide on routes: http://guides.rubyonrails.org/routing.html

Kind of long, but definitely worth the time to read.


Option 1

  resources :pages do
    collection do
      get :testy
    end
  end

results in:

testy_pages GET /pages/testy(.:format) {:action=>"testy", :controller=>"pages"}

Option 2

  resources :pages do
    member do
      get :testy
    end
  end

results in:

testy_page GET /pages/:id/testy(.:format) {:action=>"testy", :controller=>"pages"}

Option 3

  resources :pages do
    get :testy
  end

results in:

page_testy GET /pages/:page_id/testy(.:format) {:action=>"testy", :controller=>"pages"}

Any of these might be useful, though I think Option 1 is what you were asking for.


in your routes file

resources :pages do
  get 'test'
end

that will work. replace with post if necessary


Don't forget to run rake routes or write routing tests/specs


Since pages is a resource anything after it in the url will be an id with the stock options.

If you want to have a definition with 'testy' as the name you need to add a named routed to your routes.rb such as:

map.test 'testy', :controller => "pages", :action => "test"

Then to link to this you will need to call <%= link_to "testy", testy_path %>

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜