2017-01-18 18 views
1

私はかなり新しいレールです&私はこの性能の問題を抱えています。Rails既存のオブジェクトとの関連付けを熱望しています

私はユーザモデルに&のhas_many UserScoresが関連付けられています。私は特定の条件に基づいてuser_scoresのカウントを含むさまざまなユーザー統計を示すダッシュボードを準備しています。ここでは、コードの抜粋です:

def dashboard 
@users = Array.new 
users = User.order('created_at ASC') 
users.each do |u| 
    user = {} 
    user[:id] = u.id 
    user[:name] = u.nickname 
    user[:email] = u.email 
    user[:matches] = u.user_scores.count 
    user[:jokers_used] = u.user_scores.where(:joker => true).length 
    user[:jokers] = u.joker 
    user[:bonus] = u.user_scores.where(:bonus => 1).length 
    user[:joined] = u.created_at.strftime("%y/%m/%d") 
    if user[:matches] > 0 
     user[:last_activity] = u.user_scores.order('updated_at DESC').first.updated_at.strftime("%y/%m/%d") 
    else 
     user[:last_activity] = u.updated_at.strftime("%y/%m/%d") 
    end 
    @users << user 
end 
@user_count = @users.count 

エンド

私は見ています問題は、別のカウントを取得するために、ユーザーごとに繰り返さUserScoreデシベルクエリです。

複数のクエリを避ける方法はありますか?

N.B.私はビューのためのデータを準備するための私のアプローチが最適な方法であるかどうか分からないので、それに関するアドバイスやヒントも高く評価されます。

おかげまず

答えて

0

、クエリ内user_scores関連参照:

users = User.includes(:user_scores).order('created_at ASC') 

フォロードキュメント団体熱心ロードをレール:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

whereもあなたの場合は、データベースに新しいクエリを作ることに注意を関連付けは既にプリロードされています。そのため、代わりに

u.user_scores.where(:joker => true).length 
u.user_scores.where(:bonus => 1).length 

試みの:だけでなく

+0

私はそれを試しましたが、まだuser_scoresの複数のクエリが各ユーザに起こっていました – PeterB

+0

あなたの関連付けが既にプリロードされていても、 'where'がデータベースに新しいクエリを作成するためです。 'u.user_scores.where(:joker => true).length' と' u.user_scores.where(:bonus => 1)の代わりに。長さ ' try: 'u.user_scores.any? {|私| us.joker} ' と' u.user_scores.any? {|私| us.bonus == 1} ' おそらく' .user_scores.order( 'updated_at DESC')。first.updated_at.strftime( "%y /%m /%d") 'どういうわけか –

+0

それを試してみて、私にこのエラーを教えてください 引数の数が間違っています(0の場合は1) – PeterB

1

使用あなたは多くの関連を持って熱心にロードするための方法を含む

u.user_scores.count { |us| us.joker } 
u.user_scores.count { |us| us.bonus == 1 } 

あなたはおそらく何とか.user_scores.order('updated_at DESC').first.updated_at.strftime("%y/%m/%d")を書き換える必要があります。このコンセプトはここで理解できます。https://www.youtube.com/watch?v=s2EPVMqOsTQ

+0

thx、チェックアウトされます – PeterB

1

複数のクエリを減らすためには、ユーザー数を気にする必要があります。 @ Slava.Kはそれを排除するための良い説明を提供しました。 ユーザを照会するためにincludes(:user_scores)を追加し、照会を通じてDBからデータを取得したら、ルビーのメソッドを使用してコレクションを処理します。

それを理解するには、以下のコードを参照してください:

users = User.includes(:user_scores).order('created_at ASC') 

users.each do |u| 
    .... 

    user[:matches] = u.user_scores.length 
    user[:jokers_used] = u.user_scopes.select{ |score| score.joker == true }.length 
    user[:jokers] = u.joker 
    user[:bonus] = u.user_scores.select{ |score| score.bonus == 1 }.length 
    .... 
end 

はまた、あなたが応答を準備している方法は、クリーンかつ柔軟ではありません。代わりに、as_jsonメソッドをオーバーライドして、ビューで適切に消費できるjsonを準備する必要があります。 as_jsonメソッドは、デフォルトでモデル用に定義されています。詳細については、公式の文書http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.htmlまたはarticle on preparing clean json responseを参照してください。ここで、as_jsonを適切にオーバーライドする方法について説明しました。

+0

Thx Parthが指しているリソースを確認します – PeterB

+0

参考にしてくださいHTMLビューでJSONレスポンスを使用する方法 – PeterB

+0

as_jsonはハッシュを返します。これはレスポンスの準備に使用することも、質問に使用した変数として使用することもできます。 –

関連する問題