Rails& Papertrail - 在查询中包含以前的版本

时间:2013-02-10 00:11:57

标签: ruby-on-rails ruby ruby-on-rails-3.2 arel paper-trail-gem

在创建和更新文章时,我正在创建一个需要管理员批准的应用程序。我使用纸质记录来完成此操作,将每个更新存储到文章中。

更新文章时,“已发布”字段设置为false。由于我想显示文章的最新批准/已发布版本,我需要一种范围来检查文章的当前版本是否被批准,如果不是,它会搜索以前的版本,直到找到批准/发布的。

def self.published(query={})
  where(query).map do |article|
    article.published? ? article : article.last_published_version
  end.compact! || []
end

def published?()
  published
end

def last_published_version()
  return self if published?
  published_versions = versions.select{ |version| version.reify.try(:published?) } 
  published_versions.present? ? published_versions.last.reify : nil
end

现在,因为我在这里使用map,我的查询返回一个数组而不是ActiveRecord Relation。我想对发表的文章链接其他查询,所以这是一个问题。

例如,我想这样做: Article.published.where(...).order_by(...)等等

有关实现此目标的任何想法吗?

2 个答案:

答案 0 :(得分:1)

我建议直接关联并将joins 2组合在一起,以便您可以针对版本控制表添加搜索字词。我还会使用自定义版本类(不是你不能用默认版本表执行此操作)并设置您将定期访问的元数据(或需要访问以进行搜索),因为版本是序列化的,通过他们的meta选项。可能会更快,搜索/访问数据会更方便这种方式。

答案 1 :(得分:0)

如果将has_many :versions, as: :item, class_name: 'PaperTrail::Version'添加到模型中,则可以使用include(:versions)。但是,这不会急于查询所有的PaperTrail查询,例如version_at,因为该查询包括created_at范围。您可以使用version_at之类的方法来代替使用Foo.includes(:versions).first.versions.find { |f| f.created_at > date }方法。在PaperTrail的问题here中对此提出了建议。

我想为多个include(:versions) Foo,我在查询Foo后对版本进行了单独的查询

    foo_versions = PaperTrail::Version.where(
      item_type: 'Publication',
      item_id: foos.map(&:id),
    ).where("created_at >= ?", date).order(:created_at)

然后我建立了一个查找索引

    foo_index = foo_versions.each_with_object({}) do |foo, mapping|
      mapping[foo.item_id] ||= foo
    end

这使我省略了n + 1个查询情况。