1

How can I get the same result, but like posts method is a simple association?
I want to do this: "user.posts.active". Is the best solution to define :finder_sql ?

class User < ActiveRecord::Base
    has_many :created_posts, class_name: Post.name, foreign_key: :creator_id
    has_many :updated_posts, class_name: Post.name, foreign_key: :updater_id

    def posts
        (created_posts + updated_posts).flatten.uniq
    end
end
4

1 に答える 1

3

両方の投稿セットを読み込んでから Ruby で一意化するのではなく、一意のリストのみを SQL に与えることで、もう少し効率的にすることができます。

class User < ActiveRecord::Base
  def posts
    Post.where(["creator_id = ? OR updater_id = ?", self.id, self.id])
  end

  ...
end

これがより効率的である理由は、単一の応答行セットを使用して単一の DB クエリを発行し、最初から重複が返されることはなく、ActiveRecord がその行セットの Ruby オブジェクトのみをインスタンス化するためです。

比較のために、元の質問のアプローチは 2 つの DB クエリを発行し、それぞれがUserオブジェクトの配列を作成し、それら 2 つの配列を結合してから重複を削除します。余分なオブジェクトの初期化、次に配列の結合、そして重複を削除するために必要な結合された配列の反復 - すべてが一緒に結合される - は、オーバーヘッドの大部分が発生する場所です。

この種のすべての最適化と同様に、非常に小さなデータセットを扱っている場合、パフォーマンスの違いはおそらく無視できますが、この場合、単一のクエリ、単一の応答セットのアプローチは単純にスマートです。

余談ですが…

関係が定義されている場合、2 人のユーザーが同じ投稿を次々に更新すると、最新のユーザーだけが自分の ID をupdater_id? それがあなたの意図ですか?

アプリの設計によっては、特定の投稿を編集したすべてのユーザーがその投稿をupdated_posts.

于 2013-05-15T17:02:57.737 に答える