开发者

Rails restful routes and singular resources

I am having a problem with restful routes and singular resources, originally I had this code in the show view on my account resource.

<%= link_to book.title, book_path(:search => book.title) %>

and it worked fine, then I changed account to be a singular resource, e.g

from

map.resources :accounts

to

map.resource :account

and now I get the error ...

book_url failed to generate from {:search=>"Dracula", :controller=>"books", :action=>"show"}, expected: {:controller=>"books", :action=>"show"}, diff: {:search=>"Dracula"}

remove the view line of code, and everything works fine. Also changing it to

<%= link_to book.title, :controller => "books", :action => "show", :search =开发者_如何学编程> book.title %>

makes it work.

I have created a standalone rails application demonstrate my problem in isolation http://github.com/jowls/singular_resource_bug

Is this a bug? brought about through some combination of singular resources and restful routes?

This was on rails 2.3.10

thanks


The account singleton resource is a red herring. Your problem is just that you're missing the :id parameter of books_url (which is always the first argument). You can pass in additional arguments like so:

book_url(book, :search => 'Dracula') # book.id would also work here

But there must be a book. That's just how Rails's resource routes work.

It's strange if this worked before, because you should have been getting this error on your books resource the whole time.

An easy way to refactor your code to work around this would be to add a line to your controller's show action:

class BooksController < ActionController::Base

  def show
    # If :search is blank, populate it with :id's value
    params[:search] ||= params[:id]

    # your code ...
  end

end

Then just pass the search/title string in as the first argument to book_url/book_path:

# "Dracula" will be passed to your controller as params[:id]
book_path("Dracula")

Alternatively you can override the default/generated route like this:

map.resources :books

# Explicit named routes take precedence over generated ones
map.book '/books/:search', :controller => 'books', :action => 'show'

One caution against the latter idea is that it prevents you from using an :id parameter instead—it makes :search the default REST identifier, so if you tried using :id you'd have your original error, just with a different param.

I've tested these solutions in the example app you posted and they all seem to work.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜