Rails Association已经有了最新记录

我有以下型号:

class Section  'SectionRevision', :foreign_key => 'section_id' has_many :references has_many :revisions, :class_name => 'SectionRevision', :foreign_key => 'section_id' delegate :position, to: :current_revision def current_revision self.revisions.order('created_at DESC').first end end 

current_revision是最近创建的revision 。 是否可以将current_revision转换为关联,以便我可以像Section.where("current_revision.parent_section_id = '1'")那样执行查询? 或者我应该将current_revision列添加到我的数据库,而不是尝试虚拟或通过关联创建它?

我知道你想得到每个部分的最后一个修订版有parent_section_id = 1的部分;

我有类似的情况,首先,这是SQL(请将类别视为适合您的部分,将post视为修订,将user_id视为parent_section_id -sorry,如果我不将代码移动到您的需要但我必须去):

 SELECT categories.*, MAX(posts.id) as M FROM `categories` INNER JOIN `posts` ON `posts`.`category_id` = `categories`.`id` WHERE `posts`.`user_id` = 1 GROUP BY posts.user_id having M = (select id from posts where category_id=categories.id order by id desc limit 1) 

这是Rails中的查询:

 Category.select("categories.*, MAX(posts.id) as M").joins(:posts).where(:posts => {:user_id => 1}).group("posts.user_id").having("M = (select id from posts where category_id=categories.id order by id desc limit 1)") 

这是有效的,它很难看,我认为最好的方法是“剪切”查询,但如果你有太多的部分,这将是一个问题,而循环通过它们; 您也可以将此查询放入静态方法中,而且,您的第一个想法是,在sections表中包含revision_id将有助于优化查询,但会降低规范化(有时需要),并且您必须是在为该部分创建新版本时更新此字段(因此,如果您要在庞大的数据库中进行大量修订,那么如果您的服务器速度较慢,则可能不是一个好主意……)

更新我回来了,我正在做一些测试,并检查出来:

 def last_revision revisions.last end def self.last_sections_for(parent_section_id) ids = Section.includes(:revisions).collect{ |c| c.last_revision.id rescue nil }.delete_if {|x| x == nil} Section.select("sections.*, MAX(revisions.id) as M") .joins(:revisions) .where(:revisions => {:parent_section_id => parent_section_id}) .group("revisions.parent_section_id") .having("M IN (?)", ids) end 

我做了这个查询并使用了我的表(希望我很好地命名了params,它与之前的Rails查询相同,但是我更改了优化中的查询); 小心小组; 包含使得它在大型数据集中是最佳的,抱歉我找不到与has_one建立关系的方法,但我会继续使用它,但也会重新考虑你在开头提到的字段。

要获得has_many的最后一个,您可能希望执行类似于@jvnill的操作,除了向关联添加一个带有排序的范围:

 has_one :current_revision, -> { order created_at: :desc }, class_name: 'SectionRevision', foreign_key: :section_id 

这将确保您从数据库中获取最新版本。

您可以将其更改为关联,但通常,在查询上使用时,对has_onebelongs_to关联的排序总是被错误地解释。 在你的问题中,当你把它变成一个关联,那就是

 has_one :current_revision, class_name: 'SectionRevision', foreign_key: :section_id, order: 'created_at DESC' 

这个问题是当你尝试将它与其他查询结合起来时,它通常会给你错误的记录。

 >> record.current_revision # gives you the last revision >> record.joins(:current_revision).where(section_revisions: { id: 1 }) # searches for the revision where the id is 1 ordered by created_at DESC 

所以我建议你添加一个current_revision_id