ruby on rails - rails - carriles map.resources with has_many: through does not work?
routes rails examples (3)
Tengo tres modelos (relevantes), especificados así:
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
Me gustaría poder hacer referencia a todos los comments_received
para un user
con una ruta; digamos que es para aprobación por lotes de comentarios en todas las publicaciones. (Tenga en cuenta que también puede recibir comments
del user
, pero los usuarios no pueden comentar sus propias publicaciones, por lo que los comments
través de una post
son diferentes y mutuamente excluyentes) . Lógicamente, esto debería funcionar con:
map.resources :users, :has_many => [:posts, :comments, :comments_received]
Esto debería darme rutas de
user_posts_path
user_comments_path
user_comments_received_path
Los dos primeros trabajos, el último no. Lo he intentado sin el _
en comments_received
inútilmente. Estoy buscando una URL como
http://some_domain.com/users/123/comments_received
También intenté anidarlo, pero tal vez lo estoy haciendo mal. En ese caso, creo que el mapa sería:
map.resources :users do |user|
user.resources :comments
user.resources :posts, :has_many => :comments
end
y luego la url podría ser:
http://some_domain.com/users/123/posts/comments
Tal vez esta es la forma correcta de hacerlo, pero tengo la sintaxis incorrecta?
¿Estoy pensando en esto de la manera incorrecta? Me parece razonable que pueda obtener una página de todos los comments
agregados a todas las publicaciones de un usuario.
¡Gracias por tu ayuda!
Debo confesar que estoy un poco confundido por los nombres de las variables, pero antes que nada me sorprende su has_many: a través de trabajos en todo lo que se define. ¿Los modelos se comportan como espera, dejando de lado las rutas por un segundo?
En segundo lugar, y aquí es donde los nombres de las variables realmente entran en juego, las rutas tienen algunas dependencias en la pluralización, por lo que sus barras de foos y bazs podrían ser la causa del problema o podrían estar ocultando el problema. En cualquier caso, definitivamente puedes escribir algo como esto:
map.resources :users do |user|
user.resources :awards
user.resources :contest_entries do |contest_entry|
contest_entry.resources :awards
end
end
que creo que te daría:
user_path, user_awards_path, user_contest_entry_path, and user_contest_entry_awards_path.
No estoy seguro de si esto realmente responde a su pregunta, y podría ayudar tener una idea más clara de lo que está sucediendo aquí si cambiara foo, bar y baz a algo más cercano a la situación real.
Una solución rápida y sucia sería agregar un método personalizado (por ejemplo, getusercomments) a su usuario-controlador que devolvería todos los comentarios:
def getusercomments
@user = User.find(params[:id])
@comments = @user.posts.comments
end
A continuación, agregue este método a su ruta de usuario:
map.resources :users, :member => { :getusercomments => :get }
Después, debe poder llamar a lo siguiente para obtener todos los comentarios de un usuario:
http://some_domain.com/users/123/getusercomments
Aunque la sintaxis para definir el recurso y la relación modelo es similar, no se debe engañar para pensar que un recurso se asigna a un modelo. Lea lo que David Black tiene que decir .
El problema que tienes es con las rutas que estás generando. Usando la sintaxis anidada así:
map.resources :users do |user|
user.resources :posts
user.resources :comments
user.resources :comments_received
end
Y luego, ejecutando ''rake routes''
, me da (¡entre muchas otras cosas!):
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"}
Entonces parece que rails está agregando _index al final de la ruta comments_received. Admitiré que no sé por qué (¿algo que tenga que ver con chocar con la ruta de los otros comentarios?) Pero explica su problema.
Una mejor alternativa podría ser definir una acción de recopilación en su recurso de comentarios, de esta manera:
map.resources :users do |user|
user.resources :posts
user.resources :comments, :collection => {:received => :get}
end
Esto te dará las siguientes rutas:
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"}
Nota: la acción recibida ahora está en el controlador de comentarios