references rails inverse_of has_and_belongs_to_many foreign belong accepts_nested_attributes_for ruby-on-rails ruby associations orm

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.