Rails Associations has_one最新记录

Rya*_*ing 15 activerecord ruby-on-rails associations

我有以下型号:

class Section < ActiveRecord::Base
  belongs_to :page
  has_many :revisions, :class_name => '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
Run Code Online (Sandbox Code Playgroud)

current_revision最近创建的位置在哪里revision.有可能current_revision变成一个关联,所以我可以执行查询Section.where("current_revision.parent_section_id = '1'")吗?或者我应该current_revision在我的数据库中添加一列而不是尝试虚拟地或通过关联创建它?

qua*_*njn 26

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

has_one :current_revision, -> { order created_at: :desc }, 
  class_name: 'SectionRevision', foreign_key: :section_id
Run Code Online (Sandbox Code Playgroud)

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

  • 我想指出的是,当您尝试将其与不同的查询结合使用时,您必须注意注意事项。有关示例,请参阅其中的第二个代码。 (2认同)

jvn*_*ill 17

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

has_one :current_revision, class_name: 'SectionRevision', foreign_key: :section_id, order: 'created_at DESC'
Run Code Online (Sandbox Code Playgroud)

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

>> 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
Run Code Online (Sandbox Code Playgroud)

所以我建议你添加一个current_revision_id.


pab*_*rti 1

我了解您想要获取每个部分的最后修订版都有一个parent_section_id = 1的部分;

我也有类似的情况,首先,这是 SQL(请认为类别是您的部分,帖子是修订版,user_id 是parent_section_id - 抱歉,如果我不将代码移动到您的需要,但我必须去):

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)
Run Code Online (Sandbox Code Playgroud)

这是 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)")
Run Code Online (Sandbox Code Playgroud)

这可行,但很难看,我认为最好的方法是“剪切”查询,但如果你有太多部分,那么在循环它们时就会出现问题;您还可以将此查询放入静态方法中,而且,您的第一个想法是,在节表内有一个 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
Run Code Online (Sandbox Code Playgroud)

我做了这个查询并处理了我的表(希望我正确命名了参数,它与之前的 Rails 查询相同,但我更改了优化中的查询);留意这群人;包含使其在大型数据集中达到最佳状态,抱歉,我找不到与 has_one 建立关系的方法,但我会同意这一点,但也要重新考虑您在开始时提到的字段。