简体   繁体   中英

Deep model associations with Rails

Let's imagine that I have a CPA tracking system.

I would have following models: an Offer, it has some Landings, each of them has multiple Links, each of the links has a bunch of Visits.

So, I what I want is DRY code, therefore offer_id column within visits table is unacceptable. The workaround here is delegated methods like this:

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

It works nice with a single visit, eg visit.offer.id . But what if I need different visits associated with one offer?

The issue is that I'm unable to construct a valid query using ActiveRecord API. It might look like Visits.where(offer: Offer.first) , but it doesn't work this way, saying ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: visits.offer: SELECT "visits".* FROM "visits" WHERE "visits"."offer" = 1 , which is predictable.

Question: How should I organize my code to make statements like Visits.where(offer: Offer.first) work efficiently without duplicating offer_id column within visits table?

You code was organized nicely, don't need to refactor I think. You can achieve that by defining a scope in Visit like this:

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

So the query will be:

Visit.from_offer(Offer.first)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM