rails has_many:通过has_many:through

时间:2010-01-12 20:00:17

标签: ruby-on-rails ruby orm associations rails-activerecord

我想知道我可以在多大程度上使用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.businessesProvider.bids这些漂亮的快捷方式,但是如User.bids这样做呢?是否可以关联一个关联,可以这么说?

4 个答案:

答案 0 :(得分:5)

这是完全可能的,但需要一些额外的工作。以下与nested_has_many plugin结合使用的模型定义,您只需@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

但是,从出价中获取用户需要做更多工作。

答案 1 :(得分:4)

如果您只想获取记录,为什么不使用#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

虽然在我不那么谦虚的意见中你应该把这些方法链接起来,因为它更直接,而且除非你像Tadman所说的那样使用一些疯狂的自定义SQL,否则你不再能够提升性能。

答案 2 :(得分:1)

虽然这是一个非常有用的东西,但你不能通过has_many:through关系来实现。这是联接引擎的限制。

替代方法要么使用聪明的子选择,要么使用子子选择,或者有意地对表进行非规范化以减少连接深度。

例如,由于业务是在提供商的上下文中定义的,因此任何Bid元素也会间接地分配给提供商。在Bid和Provider之间建立直接关联可以直接轻松查询出价。

答案 3 :(得分:0)

没有什么能阻止你做这样的事情:

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应该会产生所需的结果,如果需要,您也可以缓存出价并做其他奇特的事情。