2

と の 2 つのタイプがblogsありpostsます。Post は、closure_tree gem (acts_as_treeバリアント) を使用して、投稿を投稿の下にネストできるようにします。また、各ブログhas_many投稿。

class Post < ActiveRecord::Base
  acts_as_tree
end

一連のブログ (たとえば、同じ作成者によるもの) が与えられた場合、それらのブログ内のすべての投稿をスコープとして (つまり、配列ではなく ActiveRecord::Relation として) 取得したいと考えています。

何かのようなもの:

Blog.all_posts_by('john')

これまでに2つのことを試しました:

配列 (スコープではない) を使用するアプローチ #1 は次のとおりです。

class Blog
  has_many :posts
  def self.all_posts_by author_name
    self.where(author_name: author_name).map(&:posts).flatten.map(&:self_and_descendants).flatten
  end
end

しかし、配列マップのアプローチは大規模なデータセットではうまく機能しない可能性があるため、スコープが必要です。

アプローチ #2: このアプローチは真のスコープを生成しますが、SQL ユニオンと SQL 文字列を使用します。

class Blog
  has_many :posts
  def self.all_posts_by author_name 
    post_collections = []
    Blog.where(author_name: author_name).each do |blog|
      post_collections = blog.posts.map(&:self_and_descendants)
    end
    posts_sql = ""
    post_collections.each do |post_collection|
      posts_sql << "( #{post_collection.to_sql} ) union "
    end
    final_sql = posts_sql.chomp('union ')
    result = Post.from("
        (
            #{final_sql}
        ) #{Post.table_name}
    ").distinct
  end
end

これはうまくいくかもしれませんが、うまくいけば利用可能なスコープマジックを使用して、より良い方法を探しています。

4

1 に答える 1

2

blog_idルートレベルの投稿だけでなく、ネストされた投稿にも保存すると、次のことができ、子孫を照会する必要はありません。

class Blog
  has_many :posts
  def self.all_posts_by author_name
    self.where(author_name: author_name).includes(:posts).map(&:posts).flatten
  end
end

ステートメントeagerは、データベースからすべての投稿をロードします。includesこれは、順次ロードするよりもはるかに高速です。http://www.spritle.com/blogs/2011/03/17/eager-loading-and-lazy-loading-in-rails-activerecord/

アップデート:

それらをスコープとして返​​したい場合は、実際にこれをPostモデルに含めるのが最善だと思います。これははるかに理にかなっているからです。

class Post
  belongs_to :blog

  def self.all_by author_name
    self.joins(:blog).where(blog: [name: author_name])
  end 
end

これも、ネストされたすべての投稿に blog_id を設定した場合にのみ機能することに注意してください。

それが本当に高性能なアプリである場合は、検索文字列がなくても、このタイプのシナリオで非常にうまく機能するため、elasticsearch のような検索インデックス エンジンを使用することをお勧めします。これにより、このようなフィルターをさらに作成して組み合わせることができますが、アプリのインフラストラクチャがさらに複雑になります。

于 2015-08-23T20:55:29.900 に答える