2009-03-31 14 views
8

Supongamos que tengo una aplicación de rieles con 3 modelos, Person, Place y Thing. Supongamos que Thing utiliza la herencia de tabla única, por lo que hay subclases FancyThing y ScaryThing. Luego hay rutas definidas con map.resources :people, :places, :things. Entonces, no hay controladores para FancyThings y ScaryThings, el ThingsController maneja cualquier tipo.Obtener ruta para la clase base de la clase STI en Rails

Ahora digo que necesito tener un código que muestre una lista de cualquier cosa que tenga enlaces a ellos. Si tengo este código en mi opinión:

<% @items.each do |item| %> 
    <%= link_to item.name, item %> 
<% end %> 

Si el artículo es una persona o un lugar, esto funciona bien, polymorphic_path se encarga de generar la ruta correcta. Pero si el artículo es un FancyThing o un ScaryThing, esto explota, porque tratará de usar fancy_thing_path, que no hay ninguna ruta para. Quiero de alguna manera hacer que use thing_path. Idealmente, habría un método en Thing y/o sus subclases que de alguna manera indica que las subclases deberían usar la clase base para generar la ruta. ¿Hay una solución elegante para esto?

+0

Este es un [boleto abierto] (http://dev.rubyonrails.org/ticket/10454) en el desarrollo de rieles. Consulte el ticket para obtener sugerencias sobre cómo lidiar con él. – MarkusQ

Respuesta

12

Esto va a hacer el truco:

<% @items.map {|i| if i.class < Thing then i.becomes(Thing) else i end}.each do |item| %> 
    <%= link_to item.name, item %> 
<% end %> 

Este utiliza la función de ActiveRecord "se convierte en" hacer un "up-cast" de todas las subclases de la clase base Thing to the Thing.

+0

Bueno, no sabía acerca de se convierte, gracias! – pjb3

+0

Esta solución es aproximadamente 10 veces más elegante de lo que esperaba. –

8

Trate de usar

map.resources :things 
map.resources :fancy_things, :controller => 'things' 
map.resources :scary_things, :controller => 'things' 
+1

+1 Por dos razones 1) Esto funciona para mí. 2) Esta respuesta parece más seca que la aceptada por @ pjb3. Gracias. – Rohit

+0

Esta solución funciona, pero tiene la desventaja de que no aplica la clase/tipo, p. si consulta una ID a través de http: // localhost: 3000/fancy_things/21 y ese elemento es en realidad de otra subclase ScaryThings, igualmente obtendrá una respuesta válida. En realidad debería dar un error, porque no es de la clase FancyThings. – Tilo

0

No tienen una respuesta correcta, pero por lo menos que puedo hacer frente a este problema utilizando el código no DRY:

map.resources: cosas,: has_many => : mete map.resources: fancy_things,: controller => 'cosas', has_many: =>: mete map.resources: scary_things,: controller => 'cosas', has_many: =>: telas

Esperamos que la problema será pronto corregido en el borde, ya que me gustaría ver fancy_things solo administra por: cosas controlador. El uso de estas rutas, el resultado final será con URLs como:/fancy_things/1, mientras que tal vez desee/cosas/1

Cuestiones relacionadas