I am new to Ruby (and probably more Rails for this) and am trying to figure out how to do this calculation efficiently.
What I have is a Training table In the training table, I have a HABTM relationship with trainers
What I am trying to do is get the percentage of each training a trainer participated in. Taking into account that there may be multiple trainers per training, so each trainers participation may only be a percentage of the total training.
I have it working with the code below but this code is FAR from efficient as it does MANY queries to get the number.
In the chart I am doing this
series: [{ name: '# Trainings', colorByPoint: true, data: [ <% User.trainers.each do |trainer| %> { name:'<%= trainer.full_name %>', y: <%= trainer_percent_of_total(trainer.id) %>, drilldown: '<%= trainer.full_name%>' }, <% end %> ] }], drilldown: { series: [ <% User.trainers.each do |trainer| %> { name: 'Initiative Count', id:'<%= trainer.full_name %>', data: [ <% Initiative.all.each do |initiative| %> { name:'<%= initiative.name %>', y: <%= initiative_percent_of_total_for_trainer(initiative.id, trainer.id) %> }, <% end %> ] }, <% end %> ] }
and two helpers
def trainer_percent_of_total(trainer_id) all_trainings_count = Training.count percentage_of_trainer = 0.00 users_count = 0
Training.each do |training| if training.users.exists?(trainer_id) users_count = training.users.count if users_count > 1 then percentage_of_trainer += (1.00/users_count).to_f else percentage_of_trainer += 1.00 end end end
trainer_percentage = 0.00 if percentage_of_trainer > 0 trainer_percentage = (percentage_of_trainer.to_f / all_trainings_count.to_f) * 100 return trainer_percentage.to_f else return 0 end end
def initiative_percent_of_total_for_trainer(initiative_id, trainer_id) all_trainings_count = Training.joins(:users).where("user_id = ?",trainer_id).count by_initiative_count=Training.joins(:users).where("initiative_id = ? AND user_id = ?",initiative_id, trainer_id).count initiative_percentage = 0.00 if by_initiative_count > 0 initiative_percentage = (by_initiative_count.to_f / all_trainings_count.to_f) * 100 return initiative_percentage.to_f else return 0 end end