代码之家  ›  专栏  ›  技术社区  ›  Vlad Faust

与Rails的深度模型关联

  •  0
  • Vlad Faust  · 技术社区  · 9 年前

    让我们假设我有一个注册会计师跟踪系统。

    我会有以下模型:一个Offer,它有一些Landings,每个都有多个链接,每个链接都有一堆访问。

    所以,我想要的是DRY代码,因此 offer_id 访问表中的列是不可接受的。这里的解决方法是如下委托方法:

    class Offer < ActiveRecord::Base
      has_many :landings
      has_many :links,  through: :landings
      has_many :visits, through: :landings
    end
    
    class Landing < ActiveRecord::Base
      belongs_to :offer
      has_many   :links
      has_many   :visits, through: :links
    end
    
    class Link < ActiveRecord::Base
      belongs_to :landing
      has_many   :visits
      delegate   :offer, to: :landing
    end
    
    class Visit < ActiveRecord::Base
      belongs_to :link
      delegate   :landing, to: :link
      delegate   :offer,   to: :link
    end
    

    单次访问效果很好,例如。 visit.offer.id 。但是,如果我需要与一个报价相关的不同访问呢?

    问题是我无法使用ActiveRecordAPI构造有效的查询。可能看起来像 Visits.where(offer: Offer.first) ,但这样做不行,说 ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: visits.offer: SELECT "visits".* FROM "visits" WHERE "visits"."offer" = 1 ,这是可预测的。

    问题: 我应该如何组织我的代码,使语句像 访问。其中(offer:offer.first) 高效工作而不重复 报价id 访问表中的列?

    1 回复  |  直到 9 年前
        1
  •  1
  •   Hieu Pham    9 年前

    你的代码组织得很好,我认为不需要重构。您可以通过在 Visit 这样地:

    class Visit < ActiveRecord::Base
      scope :from_offer, -> (offer) {
         joins(link: :landing).where(ladings: {offer_id: offer.id})
      }
    
      scope :from_landing, -> (landing) {
         joins(:link).where(links: {landing_id: landing.id})
      }
    end
    

    因此,查询将是:

    Visit.from_offer(Offer.first)