рельсы has_many: через has_many: через - PullRequest
10 голосов
/ 12 января 2010

Мне интересно, в какой степени я могу использовать ассоциации в 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? Можно ли, так сказать, ассоциировать ассоциацию?

Ответы [ 4 ]

5 голосов
/ 12 января 2010

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

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

4 голосов
/ 13 января 2010

Если вы просто хотите получить записи, почему бы не использовать команду #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, как говорит Тадман.

1 голос
/ 12 января 2010

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

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

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

0 голосов
/ 13 января 2010

Ничто не мешает вам делать что-то вроде этого 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 должен дать желаемый результат, вы также можете кэшировать ставки и делать другие интересные вещи, если хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...