Rails 3 has_one 路由
我有两个类:
class User < ActiveRecord::Base
:has_one :foo
end
class Foo < ActiveRecord::Base
:belongs_to :user
end
Foo 是可选的。
我创建了以下路由:
resources :users do
resources :foo
end
产生以下路由:
GET /users/:user_id/foo(.:format) {:controller=>"foos", :action=>"index"}
user_foos POST /users/:user_id/foo(.:format) {:controller=>"foos", :action=>"create"}
new_user_foo GET /users/:user_id/foo/new(.:format) {:controller=>"foos", :action=>"new"}
GET /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"show"}
PUT /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"update"}
user_foo DELETE /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"destroy"}
edit_user_foo GET /users/:user_id/foo/:id/edit(.:format) {:controller=>"foos", :action=>"edit"}
问题:
- 索引和显示操作似乎是多余的。是否应该删除其中之一?如果有,是哪一个?
- Show 操作中的 :id 参数似乎没有必要,因为 user_id 是 foos 表中的外键,并且每个用户只有一个 foo。我错了吗?
- 如果没有 foo,我希望有一种优雅的方式来路由到 New 操作。一种选择是测试@user.foo.nil?在 FooController 的 Show 或 Index 操作中,然后重定向到 New 操作。有更好的办法吗?
感谢您抽出时间。
I have two classes:
class User < ActiveRecord::Base
:has_one :foo
end
class Foo < ActiveRecord::Base
:belongs_to :user
end
The Foo is optional.
I created the following routing:
resources :users do
resources :foo
end
Which results in the following routes:
GET /users/:user_id/foo(.:format) {:controller=>"foos", :action=>"index"}
user_foos POST /users/:user_id/foo(.:format) {:controller=>"foos", :action=>"create"}
new_user_foo GET /users/:user_id/foo/new(.:format) {:controller=>"foos", :action=>"new"}
GET /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"show"}
PUT /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"update"}
user_foo DELETE /users/:user_id/foo/:id(.:format) {:controller=>"foos", :action=>"destroy"}
edit_user_foo GET /users/:user_id/foo/:id/edit(.:format) {:controller=>"foos", :action=>"edit"}
Questions:
- It seems like the Index and Show actions are redundant. Should one of them be removed? If so, which one?
- The :id parameter in the Show action seems unnecessary, as user_id is a foreign key in the foos table and there is only one foo per user. Am I mistaken?
- I would like to have a graceful way to route to the New action if there isn't a foo. One option would be to test @user.foo.nil? in the FooController's Show or Index action, then redirect to the New action. Is there a better way?
Thanks for your time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您的模型具有 has_one 关联,请尝试使用
resource :foo
设置路由(请注意单数方法名称“resource”,而不是“resources”)。这将设置一个单例资源路由(例如,它没有索引操作,并且成员操作没有 id 参数,因为只有一个成员)。另请参阅 http://apidock.com/rails/ActionController/Resources/resource (2.3文档,但同样适用于 3.0)。If your model has a has_one association, try to set up the route using
resource :foo
(note the singular method name "resource", not "resources"). This will set up a singleton resource route (which e.g. has no index action and member actions don't have an id param since there's only one member). See also http://apidock.com/rails/ActionController/Resources/resource (2.3 documentation, but applies to 3.0 as well afaik).我能理解为什么克雷格实际上错过了这一点。这是如此微妙的差异,我什至没有想到。唯一让我注意到的是,我的单例资源命名路由有一个奇怪的索引名称:
user_foo_index
而不是user_foos
。由于 Rails 没有使用复数形式,这是一个非常聪明的推论。
警告:以下示例通过执行以下操作来使用浅嵌套:
或者:
无论如何,回到正题,如果您设置单个资源 -
地址
例如,与articles
相反 - 你会看到这样的内容:然后正如 Andreas 刚刚指出的那样,你可能在你的路线中错误地声明了这一点:
如果你将其更改为:
你应该一切都好并且很高兴,如果您在提示中输入
rake paths
,您会看到类似的内容:注意:我知道 rake paths 的输出看起来并不完全像这样(它更加冗长),我只是为了集中注意力而简化。
希望有帮助。
I can understand why Craig missed that actually. It's such a subtle difference it didn't even cross my mind. The only thing that tipped me off is that my named routes for the singleton resource has a weird index name:
user_foo_index
instead ofuser_foos
.It's a really smart deduction from the absence of plural on the part of Rails.
Warning: The following examples use shallow nesting by either doing this:
Or that:
Anyway back to business, if you setup a singular resource –
address
as opposed toarticles
for instance – and you see something like this:Then as Andreas justly pointed out, you probably incorrectly declared this in your routes:
And if you change that to:
You should be all fine and happy and see something like this if you punch
rake routes
in your prompt:Note: I know the output of rakes routes doesn't look exactly like this (it's a lot more verbose), I'm just simplifying for the sake of focus.
Hope that helps.