rails map.resources с has_many: через не работает? - PullRequest
3 голосов
/ 12 ноября 2008

У меня есть три (соответствующие) модели, указанные следующим образом:

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 с маршрутом - скажем, для группового утверждения комментариев ко всем сообщениям. (обратите внимание, что вы также можете получить comments, сделанный user, но пользователи не могут комментировать свои собственные сообщения, поэтому comments через post отличаются и являются взаимоисключающими), По логике это должно работать с:

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

Может быть, это правильный способ сделать это, но у меня неправильный синтаксис?

Думаю ли я об этом неправильно? Мне кажется разумным, что я смогу получить страницу со всеми comments, добавленными ко всем сообщениям пользователя.

Спасибо за вашу помощь!

Ответы [ 3 ]

2 голосов
/ 30 апреля 2009

Несмотря на то, что синтаксис для деинфекции ресурсов и отношений модели похож, вы не должны обманываться, думая, что ресурс сопоставляется с моделью. Прочитайте, что Дэвид Блэк должен сказать .

Проблема в том, что вы создаете маршруты. Используя вложенный синтаксис, например, так:

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 в конец маршрута comments_received. Я признаю, что не знаю почему (что-то связанное с конфликтом других маршрутов комментариев?), Но это объясняет вашу проблему.

Хорошей альтернативой может быть определение действия по сбору в вашем ресурсе комментариев, например:

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

Примечание: полученное действие теперь находится на контроллере комментариев

0 голосов
/ 25 ноября 2008

Быстрое решение - добавить пользовательский метод (например, 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
0 голосов
/ 12 ноября 2008

Должен признаться, меня немного смущают имена переменных, но, во-первых, я удивлен, что has_many: through работает по всему, как он определен. Модели ведут себя так, как вы ожидаете, откладывая маршруты на секунду?

Во-вторых, и именно здесь имена переменных действительно вступают в игру, маршруты имеют некоторые зависимости от плюрализации, поэтому ваши полосы foos и 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 на что-то ближе к реальной ситуации.

...