问题
What's the best way to do this? I'm trying something like this, but it feels... wrong. (NOTE: It's all about the :conditions in the has_many association...)
class Submission < ActiveRecord::Base
belongs_to :checklist
has_many :jobs, :through => :checklist, :source => :job, :conditions => ["jobs.archived = false OR jobs.archived_at > #{self.created_at} OR jobs.created_at < #{self.created_at}"]
end
Rails 3.2.11, Ruby 1.9.3
What I'm trying to do
I need to pass multiple conditions on a has_many :through association and refer to the "self" model to do comparisons in those conditions.
I've found examples with multiple conditions. I've found examples with self-referencing comparisons. But I can't find anything with both of those elements. This makes me think I'm doing it wrong.
Background and definitions
A Submission records a snapshot of a Checklist and its associated Jobs at a point in time. So, I want to be able to say "submission.jobs" and see the Jobs that were associated with the Submission's Checklist at the time the Submission itself was created.*
*It's actually slightly more complicated: I want the Jobs that existed when the Submission was created AND that were not yet archived at that time.
The Checklist is dynamic and can change over time, but I always keep historical records intact via a home-grown archiving system, so the Jobs on a Checklist when a Submission was created for that Checklist would be the Checklist's Jobs where Job.created_at was before Submission.created_at (and not yet archived).
So, although a Submission belongs_to a Checklist, and the Checklist has_many Jobs, the only Jobs that ever matter for a particular Submission are the Jobs that existed (and were not yet archived) at the time the Submission was created.
回答1:
You can use a scope on Job
and perhaps a method added to Submission
:
class Job < ActiveRecord::Base
scope :unfinished_since, lambda { |timestamp|
where("archived = ? OR archived_at > ? OR created_at < ?", false, timestamp, timestamp)
}
end
class Submission < ActiveRecord::Base
belongs_to :checklist
has_many :jobs, :through => :checklist, :source => :job
def unfinished_jobs
jobs.unfinished_since(self.created_at)
end
end
来源:https://stackoverflow.com/questions/16203576/rails-associations-how-do-i-limit-scope-a-has-many-through-with-multiple-self