diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/public_body_controller.rb | 70 | ||||
-rw-r--r-- | app/models/info_request.rb | 21 | ||||
-rw-r--r-- | app/models/public_body.rb | 64 |
3 files changed, 102 insertions, 53 deletions
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 494e19353..9c3e46ded 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -196,6 +196,50 @@ class PublicBodyController < ApplicationController :disposition =>'attachment', :encoding => 'utf8') end + + # This is a helper method to take data returned by the PublicBody + # model's statistics-generating methods, and converting them to + # simpler data structure that can be rendered by a Javascript + # graph library. (This could be a class method except that we need + # access to the URL helper public_body_path.) + def simplify_stats_for_graphs(data, + column, + percentages, + graph_properties) + # Copy the data, only taking known-to-be-safe keys: + result = Hash.new { |h, k| h[k] = [] } + result.update Hash[data.select do |key, value| + ['y_values', + 'y_max', + 'totals', + 'cis_below', + 'cis_above'].include? key + end] + + # Extract data about the public bodies for the x-axis, + # tooltips, and so on: + data['public_bodies'].each_with_index do |pb, i| + result['x_values'] << i + result['x_ticks'] << [i, pb.name] + result['tooltips'] << "#{pb.name} (#{result['totals'][i]})" + result['public_bodies'] << { + 'name' => pb.name, + 'url' => public_body_path(pb) + } + end + + # Set graph metadata properties, like the title, axis labels, etc. + graph_id = "#{column}-" + graph_id += graph_properties[:highest] ? 'highest' : 'lowest' + result.update({ + 'id' => graph_id, + 'x_axis' => _('Public Bodies'), + 'y_axis' => graph_properties[:y_axis], + 'errorbars' => percentages, + 'title' => graph_properties[:title] + }) + end + def statistics unless AlaveteliConfiguration::public_body_statistics_page raise ActiveRecord::RecordNotFound.new("Page not enabled") @@ -252,28 +296,10 @@ class PublicBodyController < ApplicationController end if data - # We just need the URL and name of each public body: - data['public_bodies'].map! { |pb| - {'name' => pb.name, 'url' => public_body_path(pb)} - } - - data_to_draw = Hash.new { |h, k| h[k] = [] } - data_to_draw.update({ - 'id' => "#{column}-#{highest ? 'highest' : 'lowest'}", - 'x_axis' => _('Public Bodies'), - 'y_axis' => graph_properties[:y_axis], - 'errorbars' => percentages, - 'title' => graph_properties[:title] - }) - - data_to_draw.update(data) - data['public_bodies'].each_with_index { |pb, i| - data_to_draw['x_values'].push i - data_to_draw['x_ticks'].push [i, pb['name']] - data_to_draw['tooltips'].push pb['name'] - } - - @graph_list.push data_to_draw + @graph_list.push simplify_stats_for_graphs(data, + column, + percentages, + graph_properties) end end end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index eba620f53..9463a236e 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -1182,14 +1182,23 @@ public after_save :update_counter_cache after_destroy :update_counter_cache + # This method updates the count columns of the PublicBody that + # store the number of "not held", "to some extent successful" and + # "both visible and classified" requests when saving or destroying + # an InfoRequest associated with the body: def update_counter_cache PublicBody.skip_callback(:save, :after, :purge_in_cache) - self.public_body.info_requests_not_held_count = InfoRequest.where( - :public_body_id => self.public_body.id, - :described_state => 'not_held').count - self.public_body.info_requests_successful_count = InfoRequest.where( - :public_body_id => self.public_body.id, - :described_state => ['successful', 'partially_successful']).count + basic_params = { + :public_body_id => self.public_body_id, + :awaiting_description => false, + :prominence => 'normal' + } + [['info_requests_not_held_count', {:described_state => 'not_held'}], + ['info_requests_successful_count', {:described_state => ['successful', 'partially_successful']}], + ['info_requests_visible_classified_count', {}]].each do |column, extra_params| + params = basic_params.clone.update extra_params + self.public_body.send "#{column}=", InfoRequest.where(params).count + end self.public_body.without_revision do public_body.no_xapian_reindex = true public_body.save diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 9e77eb181..fbe2956e3 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -3,26 +3,27 @@ # # Table name: public_bodies # -# id :integer not null, primary key -# name :text not null -# short_name :text not null -# request_email :text not null -# version :integer not null -# last_edit_editor :string(255) not null -# last_edit_comment :text not null -# created_at :datetime not null -# updated_at :datetime not null -# url_name :text not null -# home_page :text default(""), not null -# notes :text default(""), not null -# first_letter :string(255) not null -# publication_scheme :text default(""), not null -# api_key :string(255) not null -# info_requests_count :integer default(0), not null -# disclosure_log :text default(""), not null -# info_requests_successful_count :integer -# info_requests_not_held_count :integer -# info_requests_overdue_count :integer +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null +# info_requests_successful_count :integer +# info_requests_not_held_count :integer +# info_requests_overdue_count :integer +# info_requests_visible_classified_count :integer # require 'csv' @@ -193,6 +194,7 @@ class PublicBody < ActiveRecord::Base acts_as_versioned self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key' self.non_versioned_columns << 'info_requests_count' << 'info_requests_successful_count' + self.non_versioned_columns << 'info_requests_count' << 'info_requests_visible_classified_count' self.non_versioned_columns << 'info_requests_not_held_count' << 'info_requests_overdue' self.non_versioned_columns << 'info_requests_overdue_count' @@ -653,20 +655,30 @@ class PublicBody < ActiveRecord::Base end end + def self.where_clause_for_stats(minimum_requests, total_column) + # When producing statistics for public bodies, we want to + # exclude any that are tagged with 'test' - we use a + # sub-select to find the IDs of those public bodies. + test_tagged_query = "SELECT model_id FROM has_tag_string_tags" \ + " WHERE model = 'PublicBody' AND name = 'test'" + "#{total_column} >= #{minimum_requests} AND id NOT IN (#{test_tagged_query})" + end + # Return data for the 'n' public bodies with the highest (or # lowest) number of requests, but only returning data for those # with at least 'minimum_requests' requests. def self.get_request_totals(n, highest, minimum_requests) ordering = "info_requests_count" ordering += " DESC" if highest - where_clause = "info_requests_count >= #{minimum_requests}" + where_clause = where_clause_for_stats minimum_requests, 'info_requests_count' public_bodies = PublicBody.order(ordering).where(where_clause).limit(n) public_bodies.reverse! if highest y_values = public_bodies.map { |pb| pb.info_requests_count } return { 'public_bodies' => public_bodies, 'y_values' => y_values, - 'y_max' => y_values.max} + 'y_max' => y_values.max, + 'totals' => y_values} end # Return data for the 'n' public bodies with the highest (or @@ -675,11 +687,12 @@ class PublicBody < ActiveRecord::Base # percentage. This only returns data for those public bodies with # at least 'minimum_requests' requests. def self.get_request_percentages(column, n, highest, minimum_requests) - total_column = "info_requests_count" + total_column = "info_requests_visible_classified_count" ordering = "y_value" ordering += " DESC" if highest y_value_column = "(cast(#{column} as float) / #{total_column})" - where_clause = "#{total_column} >= #{minimum_requests} AND #{column} IS NOT NULL" + where_clause = where_clause_for_stats minimum_requests, total_column + where_clause += " AND #{column} IS NOT NULL" public_bodies = PublicBody.select("*, #{y_value_column} AS y_value").order(ordering).where(where_clause).limit(n) public_bodies.reverse! if highest y_values = public_bodies.map { |pb| pb.y_value.to_f } @@ -709,7 +722,8 @@ class PublicBody < ActiveRecord::Base 'y_values' => y_values, 'cis_below' => cis_below, 'cis_above' => cis_above, - 'y_max' => 100} + 'y_max' => 100, + 'totals' => original_totals} end private |