我正在使用Rails 3.1,MySQL并使用3个类:Computer,LifecycleStatus& LifecycleEntry
我希望跟踪计算机LifecycleStatus的历史记录,以便LifecycleEntry中的列为:computer_id:integer,lifecycle_status_id:integer和changed_at:datetime。计算机可以在LifecycleStatus中有多个条目。
我设置了以下关联:
Computer
has_many :lifecycle_entries, :order => "changed_at DESC"
has_many :lifecycle_statuses, :through => :lifecycle_entries
LifecycleEntry
belongs_to :computer
belongs_to :lifecycle_status
LifecycleStatus
has_many :lifecycle_entries
对于特定的LifecycleStatus,我想看看哪些计算机当前(它们最近的lifecycle_entries记录)已分配给该状态。
我已设法创建正确的SQL来检索此信息,但我不确定如何将其转换为Rails关联:
SELECT id, le.computer_id, lifecycle_status_id
FROM lifecycle_entries AS le
INNER JOIN (
SELECT lemax.computer_id, MAX(changed_at) AS latest
FROM lifecycle_entries AS lemax
GROUP BY lemax.computer_id
) maxdates
ON le.changed_at = maxdates.latest
AND le.computer_id = maxdates.computer_id
WHERE lifecycle_status_id = 6
答案 0 :(得分:1)
如果您将'active'状态非规范化到LifecycleEntry本身,每次创建新条目时更新它,这似乎会更简单。每次阅读时,这都可以为您节省GROUP BY / MAX查询。
如果你有状态列,它就像LifecycleEntry.active.where(:lifecycle_status_id => 6).computers一样简单,其中active是LifecycleEntry上的一个范围。
请执行以下操作:
active
布尔字段添加到LifecycleEntry
LifecycleEntry
模型添加回调以设置有效条目这是回调:
after_save :set_active
private
def set_active
last_active_entry = self.computer.active_lifecycle_entry
if last_active_entry.nil?
update_attributes(:active => true)
elsif changed_at > last_active_entry.changed_at
last_active_entry.update_attributes(:active => false)
update_attributes(:active => true)
end
end
重要的是要注意,正在创建的LifecycleEntry可能位于当前活动的LifecycleEntry之前,因此只有在changed_at之后才能将新的LifecycleEntry设置为活动状态。此外,对于创建的第一个LifecycleEntry,始终设置为active。