ruby-on-rails - namespace - ruby and rails documentation
Rutas de recursos de anidamiento RESTfully con identificadores Ășnicos (4)
En mi aplicación Rails tengo una relación bastante normal has_many entre dos entidades. Un Foo
tiene cero o más Bars
; un Bar
pertenece exactamente a un Foo
. Tanto Foo como Bar se identifican mediante un único valor de ID entero. Estos valores son únicos en todas sus respectivas instancias.
Bar es la existencia dependiente de Foo: no tiene sentido tener un Bar sin un Foo.
Hay dos formas de hacer RESTfully referencias a instancias de estas clases. Dado un Foo.id de "100" y un Bar.id de "200":
Haga referencia a cada Foo y Bar a través de sus propias rutas de URL de "nivel superior", como las siguientes:
- / foo / 100
- / bar / 200
Barra de referencia como un recurso anidado a través de su instancia de Foo:
- / foo / 100
- / foo / 100 / bar / 200
Me gustan las rutas anidadas en el n. ° 2, ya que representa más de cerca la relación de dependencia real entre las entidades. Sin embargo, parece implicar mucho trabajo extra con muy poca ganancia. Suponiendo que sé sobre un Bar en particular, no necesito que me informen sobre un Foo en particular; Puedo derivar eso del Bar en sí. De hecho, probablemente debería estar validando el Foo enrutado donde quiera que vaya (para que no pueda hacer / foo / 150 / bar / 200, suponiendo que Bar 200 no esté asignado a Foo 150). En definitiva, no veo lo que esto me trae.
Entonces, ¿hay algún otro argumento a favor o en contra de estos dos esquemas de enrutamiento?
Punto de aclaración
Me preocupan principalmente las actualizaciones / shows / eliminaciones RESTful en determinadas barras. Para obtener una lista de barras para un Foo específico (que generalmente es la acción de "índice" en Rails), tiene mucho sentido tener una ruta anidada como / foo / 100 / bar. La página en esta ruta también podría vincularse fácilmente a / bar / x como / foo / 100 / bar / x.
Como ya sabes, cada artículo debe tener una dirección única. Sugeriría que cuanto más corta y fácil sea la dirección, mejor para todos los involucrados: su código de enrutamiento, sus aplicaciones cliente, etc. Si puede identificar una barra por su ID única, probablemente solo especifique eso en la URL.
Sin embargo, no es necesario perder la información semántica sobre la asignación del Bar a un Foo. Eso puede ser parte de la representación.
Como mejora, puede permitir que el cliente dirija Bar 200 como / foo / 100 / bar / 200, pero luego redirija a la dirección preferida / bar / 200 /, usando, por ejemplo, una respuesta 303 ("Vea Otro").
Estás buscando rutas poco profundas. Como usted señaló, la idea de tener una ruta anidada profundamente para cosas como creaciones, actualizaciones es innecesaria ya que se dirige directamente al registro deseado.
En realidad, nunca hice el enrutamiento superficial, así que pasaré el episodio de transmisión de rieles donde Ryan Bates lo explica probablemente mejor que yo: 139 Recursos anidados .
Editar: Puede leer un poco más en las guías para el enrutamiento 3.8.4 .
La anidación superficial de Rails nos ofrece lo mejor de ambos mundos: nos permite tener rutas específicas de Foo donde tiene sentido (crear, nuevo, indexar) y rutas de solo barra (de lo contrario, mostrar, editar, actualizar, destruir).
Desafortunadamente, la nueva DSL de enrutamiento en Rails 3 (que estoy usando) aún no admite enrutamiento superficial (a partir de Beta 3). Parece estar en proceso, pero no funciona por hoy.
Sin embargo, puede simularlo asignando el recurso dos veces, una vez anidado y otro poco profundo:
resources :foo do
resources :bar, :only => [:index, :new, :create]
end
resources :bar, :only => [:show, :edit, :update, :destroy]
Esto me matará hasta que la opción: superficial esté funcionando nuevamente.
Personalmente, si cada barra depende de un Foo, la opción n. ° 2 tiene más sentido. Por ejemplo, si Foo es un blog y Bar es una publicación, es mucho más lógico acceder a una publicación en particular en example.bloghosting.com/blog/1/post/2
que example.bloghosting.com/post/21
.
Haz esto con la última versión de Rails:
class Food < ActiveRecord::Base
has_many :bars
end
class Bar < ActiveRecord::Base
belongs_to :foo
end
Luego, en el enrutador Rails (/config/routes.rb):
map.resources :foos do |foo|
foo.resource :bars
end
Para obtener más información, vea Rails Routing from the Outside In y la documentación de Rails API .