Rails has_many: через has_many: через

Мне интересно, насколько я могу использовать ассоциации в Rails. Примите во внимание следующее:

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

Я могу настроить эти отличные ярлыки, например User.businesses и Provider.bids, но как насчет того, чтобы делать что-то вроде User.bids? Возможно ли связать ассоциацию, так сказать?

Ответ 1

Это вполне возможно, но требует немного дополнительной работы. Следующие определения моделей, используемые в сочетании с плагином nested_has_many, вы можете получить все ставки, принадлежащие пользователю, с помощью @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

Однако получение пользователя от заявки займет больше работы.

Ответ 2

Если вы просто хотите получить записи, почему бы не использовать use #delegate? Это работает просто отлично, по крайней мере, в сценарии, который вы описали.

class User < ActiveRecord::Base
    has_one :provider
    delegate :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

Хотя, по моему не столь скромному мнению, вам следует просто упорядочить методы, потому что это более просто, и вы больше не добьетесь повышения производительности, если не будете использовать какой-то сумасшедший пользовательский SQL, как говорит Тадман.

Ответ 3

Хотя это очень полезная вещь, вы не можете has_many: через has_many: через отношения. Это ограничение механизма соединения.

Альтернативы - либо использовать умный подвыбор, либо в этом случае выбрать суб-суб, либо преднамеренно денормализовать таблицы, чтобы уменьшить глубину соединения.

Например, поскольку бизнес определен в контексте Провайдера, понятно, что любые элементы Bid также назначаются косвенным образом Поставщику. Построение прямой связи между Bid и Provider сделало бы запросы запросов напрямую легкими.

Ответ 4

Там ничего не мешает вам делать что-то вроде этого 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

Тогда вызов @user.bids должен произвести желаемый результат, вы также можете кэшировать ставки и делать другие причудливые вещи, если хотите.