ruby on rails - inverse_of - rails has_many: a través de has_many: a través de
rails references (4)
Me pregunto hasta qué punto puedo usar asociaciones en Rails. Tenga en cuenta lo siguiente:
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
Puedo configurar estos atajos ingeniosos como User.businesses
y Provider.bids
pero ¿qué tal si hago algo como User.bids
? ¿Es posible asociar una asociación, por así decirlo?
Aunque es muy útil tenerlo, 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 usar 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 la unión.
Por ejemplo, dado que un Negocio se define en el contexto de un Proveedor, es lógico pensar que los elementos de Licitación también se asignan, de forma indirecta, a un Proveedor. Crear una asociación directa entre Oferta y Proveedor haría que las ofertas de consulta sean directamente fáciles.
Esto es completamente posible, pero necesita un poco de trabajo adicional. Las siguientes definiciones de modelo utilizadas junto con el complemento nested_has_many le permite obtener todas las ofertas que pertenecen a un usuario con solo @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, obtener un usuario de una oferta requerirá más trabajo.
No hay nada que te detenga haciendo algo como esto afaik:
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
Luego, al llamar a @ user.bids, debe obtener el resultado deseado, también puede almacenar en caché las ofertas y hacer otras cosas de lujo si lo desea.
Si solo desea recuperar los registros, ¿por qué no utilizar use #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 opinión no tan humilde debería simplemente encadenar los métodos porque es más sencillo, y ya no está logrando el aumento de rendimiento a menos que vaya con algún loco SQL personalizado como dice tadman.