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)
这将确保您从数据库中获取最新版本.
jvn*_*ill 17
您可以将其更改为关联,但通常,在查询中使用时,排序has_one或belongs_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.
我了解您想要获取每个部分的最后修订版都有一个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 建立关系的方法,但我会同意这一点,但也要重新考虑您在开始时提到的字段。