rails map.resources with has_many:through不起作用?

我有三个(相关)模型,指定如下:

class User  :posts, :source => :comments end class Post < ActiveRecord::Base belongs_to :user has_many :comments end class Comment < ActiveRecord::Base belongs_to :user belongs_to :post end 

我希望能够引用具有路由的user所有comments_received – 让我们说它是批量批准所有post的评论。 (请注意,您也可以获得用户发表的评论,但用户无法对自己的post发表评论,因此通过post发表的comments不同且相互排斥) 。 从逻辑上讲,这应该适用于:

 map.resources :users, :has_many => [:posts, :comments, :comments_received] 

这应该给我路线

 user_posts_path user_comments_path user_comments_received_path 

前两个工作,最后一个不工作。 我试过没有_comments_received无济于事。 我想找一个像这样的url

 http://some_domain.com/users/123/comments_received 

我也试过嵌套它,但也许我做错了。 在那种情况下,我认为地图将是:

 map.resources :users do |user| user.resources :comments user.resources :posts, :has_many => :comments end 

然后url可能是:

 http://some_domain.com/users/123/posts/comments 

也许这是正确的方法,但我的语法错了?

我是否以错误的方式思考这个问题? 对我而言,我应该能够获得添加到所有用户post的所有comments的页面,这似乎是合理的。

谢谢你的帮助!

尽管deinfe资源和模型关系的语法类似,但您不应该误以为资源映射到模型。 阅读David Black所说的话 。

你遇到的问题是你正在生成的路线。 使用嵌套语法如下:

 map.resources :users do |user| user.resources :posts user.resources :comments user.resources :comments_received end 

然后运行'rake routes' ,给我(在其他东西之中!):

  users GET /users {:action=>"index", :controller=>"users"} user_posts GET /users/:user_id/posts {:action=>"index", :controller=>"posts"} user_comments GET /users/:user_id/comments {:action=>"index", :controller=>"comments"} user_comments_received_index GET /users/:user_id/comments_received {:action=>"index", :controller=>"comments_received"} 

因此,rails似乎在comments_received路由的末尾添加了_index。 我承认我不知道为什么(与其他评论路线发生冲突有什么关系?)但它解释了你的问题。

一个更好的选择可能是在您的评论资源上定义一个集合操作,如下所示:

 map.resources :users do |user| user.resources :posts user.resources :comments, :collection => {:received => :get} end 

这将为您提供以下路线:

  users GET /users {:action=>"index", :controller=>"users"} user_posts GET /users/:user_id/posts {:action=>"index", :controller=>"posts"} user_comments GET /users/:user_id/comments {:action=>"index", :controller=>"comments"} received_user_comments GET /users/:user_id/comments/received {:action=>"received", :controller=>"comments"} 

注意:收到的操作现在位于注释控制器上

我必须承认,我对变量名称感到有些困惑,但首先,我很惊讶你的has_many:通过它所定义的所有方式工作。 模型是否按预期运行,将路线搁置一秒?

其次,这就是变量名称真正起作用的地方,路径对多元化有一些依赖性,所以你的foos bar和bazs可能是问题的原因,或者可能隐藏了问题。 无论如何,你绝对可以这样写:

 map.resources :users do |user| user.resources :awards user.resources :contest_entries do |contest_entry| contest_entry.resources :awards end end 

我认为会给你:

 user_path, user_awards_path, user_contest_entry_path, and user_contest_entry_awards_path. 

我不确定这是否真的能回答你的问题,如果你把foo,bar和baz变成更接近实际情况的东西,这可能有助于更清楚地了解这里发生了什么。

一个快速肮脏的解决方案是向用户控制器添加一个自定义方法(例如getusercomments),它将返回所有注释:

 def getusercomments @user = User.find(params[:id]) @comments = @user.posts.comments end 

然后将此方法添加到您的用户路由:

 map.resources :users, :member => { :getusercomments => :get } 

之后,您应该能够调用以下内容来获取用户的所有评论:

 http://some_domain.com/users/123/getusercomments