Question

We are calculating statistics for our client. Statistics are calculated for each SpecialtyLevel, and each statistic can have a number of error flags (not to be confused with validation errors). Here are the relationships (all the classes below are nested inside multiple modules, which I have omitted here for simplicity):

  class SpecialtyLevel < ActiveRecord::Base
    has_many :stats,
      :class_name =>"Specialties::Aggregate::Stat",
      :foreign_key => "specialty_level_id"

    .......
  end

      class Stat < Surveys::Stat

        belongs_to :specialty_level

        has_many :stat_flags,
          :class_name => "Surveys::PhysicianCompensation::Stats::Specialties::Aggregate::StatFlag",
          :foreign_key => "stat_id"

        ......
      end

      class StatFlag < Surveys::Stats::StatFlag
        belongs_to :stat, :class_name => "Surveys::PhysicianCompensation::Stats::Specialties::Aggregate::Stat"

        ......
      end

In the view, we display one row for each SpecialtyLevel, with one column for each Stat and another column indicating whether or not there are any error flags for that SpecialtyLevel. The client wants to be able to sort the table by the number of error flags. To achieve this, I've created a scope in the SpecialtyLevel class:

    scope :with_flag_counts,
      select("#{self.columns_with_table_name.join(', ')}, count(stat_flags.id) as stat_flags_count").
      joins("INNER JOIN #{Specialties::Aggregate::Stat.table_name} stats on stats.specialty_level_id = #{self.table_name}.id
             LEFT OUTER JOIN #{Specialties::Aggregate::StatFlag.table_name} stat_flags on stat_flags.stat_id = stats.id"
      ).
      group(self.columns_with_table_name.join(', '))

Now each row returned from the database will have a stat_flags_count field that I can sort by. This works fine, but I run into a problem when I try to paginate using this code:

  def always_show_results_count_will_paginate objects, options = {}
    if objects.total_entries <= objects.per_page
      content_tag(:div, content_tag(:span, "Showing 0-#{objects.total_entries} of #{objects.total_entries}", :class => 'info-text'))
    else
      sc_will_paginate objects, options = {}
    end
  end

For some reason, objects.total_entries returns 1. It seems that something in my scope causes Rails to do some really funky stuff with the result set that it gives me.

The question is, is there another method I can use to return the correct value? Or is there a way that I can adjust my scope to prevent this meddling from occurring?

Was it helpful?

Solution 2

The answer here is to calculate total_entries separately and pass that into the paginate method, for example:

count = SpecialtyLevel.for_participant(@participant).count
@models = SpecialtyLevel.
  with_flag_counts.
  for_participant(@participant).
  paginate(:per_page => 10, :page => page, :total_entries => count)

OTHER TIPS

The group statement makes me suspicious. You may want to fire up a debugger and step through the code and see what's actually getting returned.

Is there a special reason you're using a scope and not just an attribute on the SpecialtyLevel model? Couldn't you just add a def on SpecialtyLevel that would function as a "virtual attribute" that just returns the length of the list of StatFlags?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top