2010-01-12 17 views
9

Me pregunto en qué medida puedo usar asociaciones en Rails. Tener en cuenta lo siguiente:rails has_many: a través de has_many: a través de

class User < ActiveRecord::Base 
    has_one :provider 
    has_many :businesses, :through => :provider 
end 

class Provider < ActiveRecord::Base 
    has_many :businesses 
    has_many :bids, :through => :businesses 
    belongs_to :user 
end 

class Business < ActiveRecord::Base 
    has_many :bids 
    belongs_to :provider 
end 

class Bid < ActiveRecord::Base 
    belongs_to :business 
end 

soy capaz de configurar estos atajos ingeniosos como User.businesses y Provider.bids pero ¿qué pasa haciendo algo como User.bids? ¿Es posible asociar una asociación, por así decirlo?

Respuesta

5

Esto es completamente posible, pero necesita un poco de trabajo adicional. Las siguientes definiciones de modelos utilizados en conjunción con el nested_has_many plugin se puede recuperar todas las ofertas que pertenecen a un usuario con sólo @user.bids

class User < ActiveRecord::Base 
    has_one :provider 
    has_many :businesses, :through => :provider 
    has_many :bids, :through => :businesses 
end 

class Provider < ActiveRecord::Base 
    has_many :businesses 
    has_many :bids, :through => :businesses 
    belongs_to :user 
end 

class Business < ActiveRecord::Base 
    has_many :bids 
    belongs_to :provider 
end 

class Bid < ActiveRecord::Base 
    belongs_to :business 
end 

Sin embargo conseguir un usuario de una oferta tendrá un mayor trabajo.

+2

Es posible, pero debe tener cuidado con la profundidad con la que anida, ya que puede atascar la base de datos y la aplicación de rieles. Dicho esto, he escrito una publicación de blog que detalla cómo usar nested_has_many_through para hacer esto: http://kconrails.com/2010/01/28/nesting-has_many-through-relationships-in-ruby-on-rails/ –

2

Aunque es algo muy útil de tener, no se puede has_many: a través de una relación has_many: through. Esta es una limitación del motor de unión.

Las alternativas son utilizar una sub-selección inteligente, o en este caso una selección sub-sub, o deliberadamente desnormalizar las tablas lo suficiente para reducir la profundidad de unión.

Por ejemplo, como una empresa se define en el contexto de un proveedor, es lógico que los elementos de la oferta también se asignan, indirectamente, a un proveedor. Crear una asociación directa entre Oferta y Proveedor haría que las ofertas de consulta sean directamente fáciles.

0

No hay nada que le para hacer algo como esto que yo sepa:

class User < ActiveRecord::Base 
    has_one :provider 
    has_many :businesses, :through => :provider 

    def bids 
     user_bids = [] 
     businesses.each |business| do 
      user_bids += business.bids 
     end 
     user_bids 
    end 
end 

class Provider < ActiveRecord::Base 
    has_many :businesses 
    has_many :bids, :through => :businesses 
    belongs_to :user 
end 

class Business < ActiveRecord::Base 
    has_many :bids 
    belongs_to :provider 
end 

class Bid < ActiveRecord::Base 
    belongs_to :business 
end 

Entonces llamando @ user.bids debe producir el resultado deseado, también se puede almacenar en caché las ofertas y hacer otras cosas de lujo si lo desea.

+0

¿Cómo se '' pujarán '' las ofertas, ya que son datos no estáticos? ¿Cómo sabemos actualizar la caché? –

4

Si solo quiere buscar los registros, ¿por qué no usar #delegate? Funciona bien, al menos en el escenario que ha descrito.

class User < ActiveRecord::Base 
    has_one :provider 
    delegates :bids, :to => :provider 
end 

class Provider < ActiveRecord::Base 
    has_many :businesses 
    has_many :bids, :through => :businesses 
    belongs_to :user 
end 

class Business < ActiveRecord::Base 
    has_many :bids 
    belongs_to :provider 
end 

class Bid < ActiveRecord::Base 
    belongs_to :business 
end 

Aunque en mi no tan humilde opinión que sólo debe encadenar los métodos, porque es más sencillo, y ya no está logrando el aumento de rendimiento a menos que ir con un poco de SQL personalizado loco como dice Tadman.

Cuestiones relacionadas