2017-09-27 1 views
0

J'ai deux modèles, un User et un Exercise où un utilisateur has_many :exercises. Il y a un cache_counter sur le modèle User, exercise_countNombre de requêtes imbriquées

Je veux faire un classement basé sur le nombre d'exercices d'un utilisateur dans le mois courant. Je veux afficher les 2 utilisateurs avec les comptes d'exercice les plus élevés du mois avec le nombre. S'il y a d'autres utilisateurs avec le même nombre d'exercices que l'utilisateur de deuxième place, je veux les afficher aussi. (affichage 2+ utilisateurs)

La requête en cours, je

# User model 
scope :exercises_this_month, -> { includes(:exercises).references(:exercises) 
    .where("exercise_count > ? AND exercises.exercise_time > ? AND exercises.exercise_time < ?", 
    0 , Time.now.beginning_of_month, Time.now.end_of_month) 
} 

def User.leaders 
    limit = User.exercises_this_month.where("exercise_count > ?", 0).order(exercise_count: :desc).second.exercise_count 
    User.exercises_this_month.where("exercise_count > ? AND exercise_count >= ?", 0, limit) 
end 

retournera le haut 2+ objet utilisateur pour tous les temps. Je veux limiter cela au mois courant.

Répondre

1

Vous ne pouvez pas utiliser counter_cache ici car il stocke le nombre de tous les temps. Une autre question que vous avez est que si vous avez plusieurs joueurs ayant le même nombre d'exercices, vous manquerez ceux avec le deuxième plus grand nombre.

# Exercise.rb 
scope :exercises_this_month, -> { 
    where("exercises.exercise_time > ? AND exercises.exercise_time <= ?", 
    Time.now.beginning_of_month, Time.now.end_of_month) 
} 

#User.rb 
players_this_month = User.joins(:exercises).group(:user_id).merge(Exercise.exercises_this_month).count ## 

sorted_counts = players_this_month.values.uniq.sort 

if sorted_counts.present? 
    second_place_counts = sorted_counts[-2] || sorted_counts[-1] #in case all have the same number 
    top_two_ids = players_this_month.map { |k,v| k if v >= second_place_counts } ##user ids with top two numbers 
end 
+0

je fini par utiliser l'essence de cette réponse et a créé une portée sur le modèle d'exercice pour limiter par mois, puis créé un tableau d'utilisateurs par ces chiffres et sélectionné les meilleurs utilisateurs à partir de là – Andy

0
gem 'groupdate' 
    model 
    def self.by_month(month_num) 
     self.where("cast(strftime('%m', created_at) as int) = # 
     {Date.today.strftime("%m")}") 
    end 
    controller 
     def report 
     @posts =Post.by_month(Date.today.strftime("%m")) 
     end 
    view 
    some think like this 
     = @posts.group_by_month(:created_at).count 

Je ne sais pas ce que vous voulez, mais ce sera une grande aide, espérons profiter :)