2016-01-20 98 views
0

讓我們假設我擁有一個CPA跟蹤系統。與Rails的深層模型關聯

我會有以下模型:一個優惠,它有一些登陸,他們每個人都有多個鏈接,每個鏈接都有一堆訪問。

所以,我想要的是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。但是如果我需要與一個報價相關的不同訪問呢?

問題是我無法使用ActiveRecord API構造有效的查詢。它可能看起來像Visits.where(offer: Offer.first),但它不以這種方式工作,說ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: visits.offer: SELECT "visits".* FROM "visits" WHERE "visits"."offer" = 1,這是可預測的。

問:我應該如何安排我的代碼,使像有效Visits.where(offer: Offer.first)工作報表,而不訪問表中複製offer_id列?

回答

1

您的代碼組織得很好,不需要重構我的想法。您可以通過在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) 
+0

謝謝,它的工作原理!你能否提供類似的登陸選擇範圍('Visit.from_landing(Landing.second)')? –

+0

是的,它是類似的,男人,檢查我的更新!查看以下參考資料以獲取更多詳細信息http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html –

+0

很酷,謝謝! –