diff options
-rw-r--r-- | app/models/public_body.rb | 28 | ||||
-rw-r--r-- | config/initializers/alaveteli.rb | 1 | ||||
-rw-r--r-- | lib/date_quarter.rb | 22 | ||||
-rw-r--r-- | lib/tasks/stats.rake | 55 | ||||
-rw-r--r-- | spec/lib/date_quarter_spec.rb | 29 |
5 files changed, 135 insertions, 0 deletions
diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 9cb344f14..03ec270ee 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -60,6 +60,34 @@ class PublicBody < ActiveRecord::Base translates :name, :short_name, :request_email, :url_name, :notes, :first_letter, :publication_scheme + # Public: Search for Public Bodies whose name, short_name, request_email or + # tags contain the given query + # + # query - String to query the searchable fields + # locale - String to specify the language of the seach query + # (default: I18n.locale) + # + # Returns an ActiveRecord::Relation + def self.search(query, locale = I18n.locale) + locale = locale.to_s.gsub('-', '_') # Clean the locale string + + sql = <<-SQL + ( + lower(public_body_translations.name) like lower('%'||?||'%') + OR lower(public_body_translations.short_name) like lower('%'||?||'%') + OR lower(public_body_translations.request_email) like lower('%'||?||'%' ) + OR lower(has_tag_string_tags.name) like lower('%'||?||'%' ) + ) + AND has_tag_string_tags.model_id = public_bodies.id + AND has_tag_string_tags.model = 'PublicBody' + AND (public_body_translations.locale = ?) + SQL + + PublicBody.joins(:translations, :tags). + where([sql, query, query, query, query, locale]). + uniq + end + # Convenience methods for creating/editing translations via forms def find_translation_by_locale(locale) self.translations.find_by_locale(locale) diff --git a/config/initializers/alaveteli.rb b/config/initializers/alaveteli.rb index c7672d05b..e909013aa 100644 --- a/config/initializers/alaveteli.rb +++ b/config/initializers/alaveteli.rb @@ -52,6 +52,7 @@ require 'alaveteli_localization' require 'message_prominence' require 'theme' require 'xapian_queries' +require 'date_quarter' AlaveteliLocalization.set_locales(AlaveteliConfiguration::available_locales, AlaveteliConfiguration::default_locale) diff --git a/lib/date_quarter.rb b/lib/date_quarter.rb new file mode 100644 index 000000000..ac159b420 --- /dev/null +++ b/lib/date_quarter.rb @@ -0,0 +1,22 @@ +module DateQuarter + extend self + + def quarters_between(start_at, finish_at) + results = [] + + quarter_start = start_at.beginning_of_quarter + quarter_end = start_at.end_of_quarter + + while quarter_end <= finish_at.end_of_quarter do + # Collect these + results << [quarter_start, quarter_end] + + # Update dates + quarter_start = quarter_end + 1.second + quarter_end = quarter_start.end_of_quarter + end + + results + end + +end diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake index 38eb15996..f09594529 100644 --- a/lib/tasks/stats.rake +++ b/lib/tasks/stats.rake @@ -97,6 +97,61 @@ namespace :stats do end end + desc <<-DESC +Prints the per-quarter number of created FOI Requests made to each Public Body found by the query. +Specify the search query as QUERY='london school' +DESC + task :number_of_requests_created => :environment do + query = ENV['QUERY'] + start_at = PublicBody.minimum(:created_at) + finish_at = PublicBody.maximum(:created_at) + public_bodies = PublicBody.search(query) + quarters = DateQuarter.quarters_between(start_at, finish_at) + + # Headers + headers = ['Body'] + quarters.map { |date_tuple| date_tuple.join('~') } + puts headers.join(",") + + public_bodies.each do |body| + stats = quarters.map do |quarter| + conditions = ['created_at >= ? AND created_at < ?', quarter[0], quarter[1]] + count = body.info_requests.count(:conditions => conditions) + count ? count : 0 + end + + row = [body.name] + stats + puts row.join(",") + end + end + + desc <<-DESC +Prints the per-quarter number of successful FOI Requests made to each Public Body found by the query. +Specify the search query as QUERY='london school' +DESC + task :number_of_requests_successful => :environment do + query = ENV['QUERY'] + start_at = PublicBody.minimum(:created_at) + finish_at = PublicBody.maximum(:created_at) + public_bodies = PublicBody.search(query) + quarters = DateQuarter.quarters_between(start_at, finish_at) + + # Headers + headers = ['Body'] + quarters.map { |date_tuple| date_tuple.join('~') } + puts headers.join(",") + + public_bodies.each do |body| + stats = quarters.map do |quarter| + conditions = ['created_at >= ? AND created_at < ? AND described_state = ?', + quarter[0], quarter[1], 'successful'] + count = body.info_requests.count(:conditions => conditions) + count ? count : 0 + end + + row = [body.name] + stats + puts row.join(",") + end + end + desc 'Update statistics in the public_bodies table' task :update_public_bodies_stats => :environment do verbose = ENV['VERBOSE'] == '1' diff --git a/spec/lib/date_quarter_spec.rb b/spec/lib/date_quarter_spec.rb new file mode 100644 index 000000000..29c2eb28d --- /dev/null +++ b/spec/lib/date_quarter_spec.rb @@ -0,0 +1,29 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe DateQuarter do + include DateQuarter + + describe :quarters_between do + + it 'returns all the quarters in a year' do + # This is a bit of a convoluted spec, since we have to convert each + # Time in to an Integer to make a reasonable comparison + # See http://makandracards.com/makandra/1057-why-two-ruby-time-objects-are-not-equal-although-they-appear-to-be + start = Time.parse('2014-01-01') + finish = Time.parse('2014-12-31') + + expected = [['Wed Jan 01 00:00:00 +0000 2014', 'Mon Mar 31 23:59:59 +0000 2014'], + ['Tue Apr 01 00:00:00 +0000 2014', 'Mon Jun 30 23:59:59 +0000 2014'], + ['Tue Jul 01 00:00:00 +0000 2014', 'Tue Sep 30 23:59:59 +0000 2014'], + ['Wed Oct 01 00:00:00 +0000 2014', 'Wed Dec 31 23:59:59 +0000 2014']]. + map { |pair| [Time.parse(pair[0]).to_i, Time.parse(pair[1]).to_i] } + + quarters_between(start, finish).each_with_index do |pair, i| + pair.map!(&:to_i) + pair.should == expected[i] + end + end + + end + +end |