【问题标题】:rails map.resources with has_many :through doesn't work?带有 has_many 的 rails map.resources :through 不起作用?
【发布时间】:2008-11-11 21:02:26
【问题描述】:

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

class User < ActiveRecord::Base
  has_many :posts
  has_many :comments
  has_many :comments_received, :through => :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

我希望能够引用所有 comments_received 以获取带有路线的 user - 假设这是为了对所有帖子的 cmets 进行批量批准。 (注意你也可以得到user发的comments,但是用户不能对自己的帖子发表评论,所以comments通过post是不同的,互斥的)。从逻辑上讲,这应该适用于:

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

这应该给我路线

user_posts_path
user_comments_path
user_comments_received_path

前两个有效,最后一个无效。我试过没有comments_received 中的_,但无济于事。我正在寻找类似的网址

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

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

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

然后网址可能是:

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

也许这是正确的做法,但我的语法错误?

我是不是想错了?对我来说,我应该能够将所有comments 添加到所有用户的帖子中,这似乎是合理的。

感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails resources map has-many


    【解决方案1】:

    尽管定义资源和模型关系的语法相似,但您不应误以为资源映射到模型。阅读 David Black has to say 的内容。

    您遇到的问题是您生成的路线。像这样使用嵌套语法:

    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 正在将 _index 添加到 cmets_received 路由的末尾。我承认我不知道为什么(与与其他 cmets 路线发生冲突有关?)但它解释了您的问题。

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

    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"}
    

    注意:接收到的动作现在在 cmets 控制器上

    【讨论】:

      【解决方案2】:

      我必须承认,我对变量名有点困惑,但首先,我很惊讶你的 has_many :through 以它定义的方式工作。模型的行为是否符合您的预期,将路线搁置一秒钟?

      其次,这就是变量名真正发挥作用的地方,路由依赖于复数形式,因此您的 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 更改为更接近真实情况的内容,这可能有助于更清楚地了解这里发生的情况。

      【讨论】:

      • 好吧,这不完全是我正在做的事情,但它足够接近,可以将 Foo 称为用户、Bar 一个帖子、Baz 一个评论,并且 xxx 是“已收到”。目标是获得一条路线,在给定用户的所有帖子上显示所有 cmets,并注意用户不能对自己的帖子发表评论。
      【解决方案3】:

      一种快速且简单的解决方案是向您的用户控制器添加一个自定义方法(例如 getusercmets),该方法将返回所有 cmets:

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

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

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

      之后您应该可以调用以下命令来获取用户的所有 cmets:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-26
        • 2019-03-04
        • 2020-03-07
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-06
        • 1970-01-01
        相关资源
        最近更新 更多