2016-03-31 17 views
1

具体的な例がありますが、一般的な質問は次のとおりです。一致するフィルタ値の配列を持つときにレコードを取り出す最適な方法は何ですか?Ruby on Railsのフィルタ値の配列での最適な検索?

class Relationship < ActiveRecord::Base 
    belongs_to :follower, class_name: "User" 
    belongs_to :followed, class_name: "User" 
    validates :follower_id, presence: true 
    validates :followed_id, presence: true 
end 

私は時系列あなたの以下の記事を命じ返す関数を書きたい:

は、私は、ユーザーhas_many :posts

UserPostレコードを持っていると私はこのようになりますRelationshipモデルを持っていると言いますあなたのフォローしているユーザーの投稿はすべてフォローしています。フォローしているユーザーからの重複や投稿は除きます。その後、自分の投稿や順序、それらをコンパイル

users = [] 
@user.following.each do |f| 
    f.following.each do |ff| 
    users << ff 
    end 
end 

# dedupe 
users = users.uniq 

#remove self and following 
users.delete(@user) 
@user.following.each do |f| 
    users.delete(f) 
end 

私のソリューションは、最初に関心のあるすべてのユーザーの配列をコンパイルすることです

posts = [] 
users.each do |u| 
    posts += u.posts 
end 
posts.sort_by!{|x| x[:created_at]}.reverse! 

私はこれを行うには良い方法があると思いますActive Record関数を使用していますが、配列でそれらを動作させる方法を理解することはできません。私は、ユーザーid値の代わりに、フルモデルの配列をコンパイルし、ポストの配列を取得するには、このコードを実行しようとした場合たとえば、:

posts = Post.where(
    user_id: user_ids 
).order('created_at DESC').limit(21) 

それは空の配列を返します。私の現在のソリューションよりもフィルタ値の配列で検索する方が良いでしょうか?

更新:追加のモーダルコード:

class Post < ActiveRecord::Base 
    belongs_to :user 
    ... 

User.rb

class User < ActiveRecord::Base 
    has_many :photos 
    has_many :active_relationships, class_name: "Relationship", 
           foreign_key: "follower_id", 
           dependent: :destroy 
    has_many :passive_relationships, class_name: "Relationship", 
           foreign_key: "followed_id", 
           dependent: :destroy 
    has_many :following, through: :active_relationships, source: :followed 
    has_many :followers, through: :passive_relationships, source: :follower 
    ... 
+0

'User'' has_many:followsは::follower、class_name: 'Relationship''ですか? – Aetherus

+0

はい、モーダルコード – Cbas

+0

で更新しました。ActiveRecordコレクションを反復処理するときは、 'each'の代わりに' find_each'を使います。 'find_each'は一度にすべてではなく、バッチでレコードをコレクションからロードします。これは明らかにあなたのメモリ負荷に対して安全です。 –

答えて

1

user_idsを使用してのあなたのアイデアは良いものです。そのクエリで空の配列が返された場合は、user_idが期待したものであることを確認しましたか?

コードに関しては、Enumerable#map#flat_mapを調べる必要があります。それらは、それぞれのループで何をしようとしているのかを達成するための組み込みのルビーメソッドです。

user_ids = user.followings.flat_map { |following| following.following_id } 
user_ids.uniq! 
user_ids -= [user.id, user.following_ids].flatten 
Post.where(user_id: user_ids).order(id: :desc).limit(21) 

注:created_atとは、IDを作成するために従わなければならないので、それはインデックスを持っているはずなので、私はIDというよりはcreated_atに基づいて検索を検討するあなたのコードは次のように低下​​する可能性があります。

関連する問題