spout 0.10.2 → 0.11.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/README.md +3 -30
  4. data/lib/spout/commands/coverage.rb +2 -1
  5. data/lib/spout/commands/deploy.rb +82 -77
  6. data/lib/spout/commands/exporter.rb +2 -3
  7. data/lib/spout/commands/graphs.rb +68 -67
  8. data/lib/spout/commands/help.rb +155 -0
  9. data/lib/spout/helpers/array_statistics.rb +36 -30
  10. data/lib/spout/helpers/chart_types.rb +2 -2
  11. data/lib/spout/helpers/config_reader.rb +5 -5
  12. data/lib/spout/helpers/json_request.rb +1 -2
  13. data/lib/spout/helpers/json_request_generic.rb +87 -0
  14. data/lib/spout/helpers/quietly.rb +2 -4
  15. data/lib/spout/helpers/semantic.rb +7 -11
  16. data/lib/spout/helpers/send_file.rb +23 -25
  17. data/lib/spout/helpers/subject_loader.rb +41 -32
  18. data/lib/spout/helpers/table_formatting.rb +7 -6
  19. data/lib/spout/models/bucket.rb +5 -4
  20. data/lib/spout/models/coverage_result.rb +1 -1
  21. data/lib/spout/models/dictionary.rb +3 -1
  22. data/lib/spout/models/domain.rb +7 -6
  23. data/lib/spout/models/empty.rb +17 -0
  24. data/lib/spout/models/form.rb +8 -5
  25. data/lib/spout/models/graphables/default.rb +41 -18
  26. data/lib/spout/models/graphables/histogram.rb +6 -7
  27. data/lib/spout/models/graphables.rb +3 -5
  28. data/lib/spout/models/option.rb +6 -2
  29. data/lib/spout/models/outlier_result.rb +3 -3
  30. data/lib/spout/models/record.rb +21 -3
  31. data/lib/spout/models/subject.rb +4 -7
  32. data/lib/spout/models/tables/choices_vs_choices.rb +29 -17
  33. data/lib/spout/models/tables/choices_vs_numeric.rb +19 -12
  34. data/lib/spout/models/tables/default.rb +19 -32
  35. data/lib/spout/models/tables/numeric_vs_choices.rb +9 -13
  36. data/lib/spout/models/tables/numeric_vs_numeric.rb +9 -11
  37. data/lib/spout/models/tables.rb +4 -6
  38. data/lib/spout/models/variable.rb +51 -13
  39. data/lib/spout/tasks/engine.rake +1 -1
  40. data/lib/spout/templates/ruby-version +1 -1
  41. data/lib/spout/templates/travis.yml +1 -1
  42. data/lib/spout/tests/domain_format.rb +2 -2
  43. data/lib/spout/tests/domain_name_format.rb +15 -0
  44. data/lib/spout/tests/form_name_format.rb +14 -0
  45. data/lib/spout/tests/variable_name_format.rb +14 -0
  46. data/lib/spout/tests.rb +18 -13
  47. data/lib/spout/version.rb +3 -3
  48. data/lib/spout/views/index.html.erb +2 -2
  49. data/lib/spout/views/outliers.html.erb +1 -1
  50. data/lib/spout.rb +13 -58
  51. data/spout.gemspec +14 -15
  52. metadata +25 -25
  53. data/lib/spout/commands/images.rb +0 -199
  54. data/lib/spout/support/javascripts/data.js +0 -17
  55. data/lib/spout/support/javascripts/highcharts-convert.js +0 -583
  56. data/lib/spout/support/javascripts/highcharts-more.js +0 -50
  57. data/lib/spout/support/javascripts/highstock.js +0 -353
  58. data/lib/spout/support/javascripts/jquery.1.9.1.min.js +0 -5
@@ -5,7 +5,6 @@ module Spout
5
5
  module Models
6
6
  module Graphables
7
7
  class Default
8
-
9
8
  attr_reader :variable, :chart_variable, :stratification_variable, :subjects
10
9
 
11
10
  def initialize(variable, chart_variable, stratification_variable, subjects)
@@ -13,27 +12,24 @@ module Spout
13
12
  @chart_variable = chart_variable
14
13
  @stratification_variable = stratification_variable
15
14
  @subjects = subjects
16
-
17
- @values = subjects.collect(&@variable.id.to_sym) rescue @values = []
18
- @values_unique = @values.uniq
19
-
15
+ begin
16
+ @values_unique = subjects.collect(&@variable.id.to_sym).reject { |a| a.is_a?(Spout::Models::Empty) }.uniq
17
+ rescue
18
+ @values_unique = []
19
+ end
20
20
  @buckets = continuous_buckets
21
21
  end
22
22
 
23
23
  def to_hash
24
- if valid?
25
- { title: title, subtitle: subtitle, categories: categories, units: units, series: series, stacking: stacking, x_axis_title: x_axis_title }
26
- else
27
- nil
28
- end
24
+ { title: title, subtitle: subtitle, categories: categories, units: units, series: series, stacking: stacking, x_axis_title: x_axis_title } if valid?
29
25
  end
30
26
 
31
27
  def valid?
32
- if @variable == nil or @chart_variable == nil or @values == []
28
+ if @variable.nil? || @chart_variable.nil? || @values_unique == []
33
29
  false
34
- elsif @variable.type == 'choices' and @variable.domain.options == []
30
+ elsif @variable.type == 'choices' && @variable.domain.options == []
35
31
  false
36
- elsif @chart_variable.type == 'choices' and @chart_variable.domain.options == []
32
+ elsif @chart_variable.type == 'choices' && @chart_variable.domain.options == []
37
33
  false
38
34
  else
39
35
  true
@@ -45,7 +41,7 @@ module Spout
45
41
  end
46
42
 
47
43
  def subtitle
48
- "By Visit"
44
+ 'By Visit'
49
45
  end
50
46
 
51
47
  def categories
@@ -71,11 +67,17 @@ module Spout
71
67
  private
72
68
 
73
69
  def continuous_buckets
74
- values_numeric = @values.select{|v| v.kind_of? Numeric}
70
+ values_numeric = @values_unique.select { |v| v.is_a? Numeric }
71
+
75
72
  return [] if values_numeric.count == 0
76
73
  minimum_bucket = values_numeric.min
77
74
  maximum_bucket = values_numeric.max
78
75
  max_buckets = 12
76
+ if all_integer?(values_numeric) && (maximum_bucket - minimum_bucket < max_buckets)
77
+ max_buckets = maximum_bucket - minimum_bucket
78
+ return discrete_buckets
79
+ end
80
+
79
81
  bucket_size = ((maximum_bucket - minimum_bucket) / max_buckets.to_f)
80
82
  precision = (bucket_size == 0 ? 0 : [-Math.log10(bucket_size).floor, 0].max)
81
83
 
@@ -88,8 +90,30 @@ module Spout
88
90
  buckets
89
91
  end
90
92
 
93
+ def discrete_buckets
94
+ values_numeric = @values_unique.select { |v| v.is_a? Numeric }
95
+ minimum_bucket = values_numeric.min
96
+ maximum_bucket = values_numeric.max
97
+ max_buckets = maximum_bucket - minimum_bucket + 1
98
+ bucket_size = 1
99
+ precision = 0
100
+
101
+ buckets = []
102
+ (0..(max_buckets-1)).to_a.each do |index|
103
+ start = (minimum_bucket + index * bucket_size)
104
+ stop = start
105
+ buckets << Spout::Models::Bucket.new(start.round(precision), stop.round(precision), discrete: true)
106
+ end
107
+ buckets
108
+ end
109
+
110
+ def all_integer?(values_numeric)
111
+ count = values_numeric.count { |v| Integer(format('%.0f', v)) == v }
112
+ count == values_numeric.size
113
+ end
114
+
91
115
  def get_bucket(value)
92
- return nil if @buckets.size == 0 or not value.kind_of?(Numeric)
116
+ return nil if @buckets.size == 0 || !value.is_a?(Numeric)
93
117
  @buckets.each do |b|
94
118
  return b.display_name if b.in_bucket?(value)
95
119
  end
@@ -105,10 +129,9 @@ module Spout
105
129
  # b) or are marked as missing codes but represented in the dataset
106
130
  def filtered_domain_options(variable)
107
131
  variable.domain.options.select do |o|
108
- o.missing != true or (o.missing == true and @values_unique.include?(o.value))
132
+ o.missing != true || (o.missing == true && @values_unique.include?(o.value))
109
133
  end
110
134
  end
111
-
112
135
  end
113
136
  end
114
137
  end
@@ -3,8 +3,8 @@ require 'spout/models/graphables/default'
3
3
  module Spout
4
4
  module Models
5
5
  module Graphables
6
+ # Generates data for variable histograms
6
7
  class Histogram < Spout::Models::Graphables::Default
7
-
8
8
  def title
9
9
  @variable.display_name
10
10
  end
@@ -23,18 +23,18 @@ module Spout
23
23
 
24
24
  def series
25
25
  @chart_variable.domain.options.collect do |option|
26
- visit_subjects = @subjects.select{ |s| s.send(@chart_variable.id) == option.value and s.send(@variable.id) != nil } rescue visit_subjects = []
27
- visit_subject_values = visit_subjects.collect(&@variable.id.to_sym).sort rescue visit_subject_values = []
26
+ visit_subjects = @subjects.select{ |s| s.send(@chart_variable.id) == option.value && !s.send(@variable.id).nil? && !s.send(@variable.id).is_a?(Spout::Models::Empty) } rescue visit_subjects = []
27
+ visit_subject_values = visit_subjects.collect(&@variable.id.to_sym).sort # rescue visit_subject_values = []
28
28
  next unless visit_subject_values.size > 0
29
29
 
30
30
  data = []
31
31
 
32
32
  if @variable.type == 'choices'
33
- data = filtered_domain_options(@variable).collect do |option|
34
- visit_subject_values.select{ |v| v == option.value }.count
33
+ data = filtered_domain_options(@variable).collect do |o|
34
+ visit_subject_values.select { |v| v == o.value }.count
35
35
  end
36
36
  else
37
- visit_subject_values.group_by{|v| get_bucket(v) }.each do |key, values|
37
+ visit_subject_values.group_by { |v| get_bucket(v) }.each do |key, values|
38
38
  data[categories.index(key)] = values.count if categories.index(key)
39
39
  end
40
40
  end
@@ -46,7 +46,6 @@ module Spout
46
46
  def x_axis_title
47
47
  @variable.units
48
48
  end
49
-
50
49
  end
51
50
  end
52
51
  end
@@ -5,11 +5,9 @@ require 'spout/models/graphables/choices_vs_choices'
5
5
  require 'spout/models/graphables/numeric_vs_numeric'
6
6
  require 'spout/models/graphables/choices_vs_numeric'
7
7
 
8
-
9
8
  module Spout
10
9
  module Models
11
10
  module Graphables
12
-
13
11
  DEFAULT_CLASS = Spout::Models::Graphables::Default
14
12
  GRAPHABLE_CLASSES = {
15
13
  'histogram' => Spout::Models::Graphables::Histogram,
@@ -25,7 +23,7 @@ module Spout
25
23
  end
26
24
 
27
25
  def self.get_graph_type(variable, chart_variable, stratification_variable)
28
- if stratification_variable == nil
26
+ if stratification_variable.nil?
29
27
  'histogram'
30
28
  else
31
29
  "#{variable_to_graph_type(variable)}_vs_#{variable_to_graph_type(chart_variable)}"
@@ -34,13 +32,13 @@ module Spout
34
32
 
35
33
  def self.variable_to_graph_type(variable)
36
34
  variable_type = (variable ? variable.type : nil)
37
- case variable_type when 'numeric', 'integer'
35
+ case variable_type
36
+ when 'numeric', 'integer'
38
37
  'numeric'
39
38
  else
40
39
  variable_type
41
40
  end
42
41
  end
43
-
44
42
  end
45
43
  end
46
44
  end
@@ -4,11 +4,15 @@ module Spout
4
4
  attr_accessor :display_name, :value, :description, :missing
5
5
 
6
6
  def initialize(option_hash)
7
- %w( display_name value description missing ).each do |method|
8
- instance_variable_set("@#{method}", (option_hash.kind_of?(Hash) ? option_hash : {})[method])
7
+ %w(display_name value description missing).each do |method|
8
+ instance_variable_set("@#{method}", (option_hash.is_a?(Hash) ? option_hash : {})[method])
9
9
  end
10
10
  end
11
11
 
12
+ def deploy_params
13
+ { display_name: display_name, value: value, description: description,
14
+ missing: missing }
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -22,9 +22,9 @@ module Spout
22
22
  2
23
23
  end
24
24
  variable = Spout::Helpers::JsonLoader::get_variable(method)
25
- @units = (variable.kind_of?(Hash) ? variable['units'] : nil)
26
- @display_name = (variable.kind_of?(Hash) ? variable['display_name'] : nil)
27
- @variable_type = (variable.kind_of?(Hash) ? variable['type'] : nil)
25
+ @units = (variable.is_a?(Hash) ? variable['units'] : nil)
26
+ @display_name = (variable.is_a?(Hash) ? variable['display_name'] : nil)
27
+ @variable_type = (variable.is_a?(Hash) ? variable['type'] : nil)
28
28
  @median = @values.median
29
29
  end
30
30
 
@@ -3,16 +3,34 @@ require 'fileutils'
3
3
 
4
4
  module Spout
5
5
  module Models
6
+ # Base class for spout variables, forms, and domains that are read from JSON
7
+ # files
6
8
  class Record
7
-
8
9
  class << self
9
10
  # Only returns records with zero json errors, nil otherwise
10
11
  def find_by_id(id)
11
- dictionary_root = FileUtils.pwd # '.'
12
- file_name = Dir.glob(File.join(dictionary_root, "#{self.name.split("::").last.to_s.downcase}s", "**", "#{id.to_s.downcase}.json"), File::FNM_CASEFOLD).first
12
+ file_name = Dir.glob(expected_path(id), File::FNM_CASEFOLD).first
13
13
  variable = new(file_name, dictionary_root)
14
14
  (variable.errors.size > 0 ? nil : variable)
15
15
  end
16
+
17
+ private
18
+
19
+ def record_folder
20
+ "#{name.split('::').last.to_s.downcase}s"
21
+ end
22
+
23
+ def expected_filename(id)
24
+ "#{id.to_s.downcase}.json"
25
+ end
26
+
27
+ def expected_path(id)
28
+ File.join(dictionary_root, record_folder, '**', expected_filename(id))
29
+ end
30
+
31
+ def dictionary_root
32
+ FileUtils.pwd
33
+ end
16
34
  end
17
35
  end
18
36
  end
@@ -1,17 +1,14 @@
1
- # subject.rb
2
-
3
1
  module Spout
4
2
  module Models
5
-
3
+ # Subject encapsulates records for individuals specified by an identifier
6
4
  class Subject
7
- attr_accessor :_visit
5
+ attr_accessor :_visit, :_csv
8
6
 
9
- def self.create(&block)
10
- subject = self.new
7
+ def self.create
8
+ subject = new
11
9
  yield subject if block_given?
12
10
  subject
13
11
  end
14
-
15
12
  end
16
13
  end
17
14
  end
@@ -3,49 +3,61 @@ require 'spout/models/tables/default'
3
3
  module Spout
4
4
  module Models
5
5
  module Tables
6
+ # Generates a table of
6
7
  class ChoicesVsChoices < Spout::Models::Tables::Default
7
-
8
8
  def title
9
9
  "#{@variable.display_name} vs #{@chart_variable.display_name}"
10
10
  end
11
11
 
12
12
  def headers
13
- [ [""] + filtered_domain_options(@chart_variable).collect(&:display_name) + ["Total"] ]
13
+ header_row = [''] + filtered_domain_options(@chart_variable).collect(&:display_name)
14
+ if @totals
15
+ header_row += ['Total']
16
+ end
17
+ [header_row]
14
18
  end
15
19
 
16
20
  def footers
17
21
  total_values = filtered_domain_options(@chart_variable).collect do |option|
18
- total_count = @filtered_subjects.select{|s| s.send(@chart_variable.id) == option.value }.count
19
- { text: (total_count == 0 ? "-" : Spout::Helpers::TableFormatting::format_number(total_count, :count)), style: "font-weight:bold" }
22
+ total_count = @filtered_subjects.count { |s| s.send(@chart_variable.id) == option.value }
23
+ { text: (Spout::Helpers::TableFormatting.format_number(total_count, :count)), style: 'font-weight:bold' }
24
+ end
25
+ footer_row = [{ text: 'Total', style: 'font-weight:bold' }] + total_values
26
+ if @totals
27
+ footer_row += [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count, :count), style: 'font-weight:bold' }]
20
28
  end
21
- [
22
- [{ text: "Total", style: "font-weight:bold" }] + total_values + [{ text: Spout::Helpers::TableFormatting::format_number(@filtered_subjects.count, :count), style: 'font-weight:bold'}]
23
- ]
29
+ [footer_row]
24
30
  end
25
31
 
26
32
  def rows
27
- rows_result = []
28
33
  rows_result = filtered_domain_options(@variable).collect do |option|
29
- row_subjects = @filtered_subjects.select{ |s| s.send(@variable.id) == option.value }
34
+ row_subjects = @filtered_subjects.select { |s| s.send(@variable.id) == option.value }
30
35
  row_cells = filtered_domain_options(@chart_variable).collect do |chart_option|
31
- count = row_subjects.select{ |s| s.send(@chart_variable.id) == chart_option.value }.count
32
- count > 0 ? Spout::Helpers::TableFormatting::format_number(count, :count) : { text: '-', class: 'text-muted' }
36
+ count = row_subjects.count { |s| s.send(@chart_variable.id) == chart_option.value }
37
+ count > 0 ? Spout::Helpers::TableFormatting.format_number(count, :count) : { text: '-', class: 'text-muted' }
33
38
  end
34
39
 
35
- total = row_subjects.count
40
+ row = [option.display_name] + row_cells
36
41
 
37
- [option.display_name] + row_cells + [total == 0 ? { text: '-', class: 'text-muted' } : { text: Spout::Helpers::TableFormatting::format_number(total, :count), style: 'font-weight:bold'}]
42
+ if @totals
43
+ total = row_subjects.count
44
+ row += [total == 0 ? { text: '-', class: 'text-muted' } : { text: Spout::Helpers::TableFormatting.format_number(total, :count), style: 'font-weight:bold' }]
45
+ end
46
+ row
38
47
  end
39
48
 
40
- if @filtered_subjects.select{|s| s.send(@variable.id) == nil }.count > 0
49
+ if @filtered_subjects.count { |s| s.send(@variable.id).is_a?(Spout::Models::Empty) } > 0
41
50
  unknown_values = filtered_domain_options(@chart_variable).collect do |chart_option|
42
- { text: Spout::Helpers::TableFormatting::format_number(@filtered_subjects.select{ |s| s.send(@chart_variable.id) == chart_option.value and s.send(@variable.id) == nil }.count, :count), class: 'text-muted' }
51
+ { text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count { |s| s.send(@chart_variable.id) == chart_option.value && s.send(@variable.id).is_a?(Spout::Models::Empty) }, :count), class: 'text-muted' }
52
+ end
53
+ unknown_row = [{ text: 'Unknown', class: 'text-muted' }] + unknown_values
54
+ if @totals
55
+ unknown_row += [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count { |s| s.send(@variable.id).is_a?(Spout::Models::Empty) }, :count), style: 'font-weight:bold', class: 'text-muted' }]
43
56
  end
44
- rows_result << [{ text: 'Unknown', class: 'text-muted'}] + unknown_values + [ { text: Spout::Helpers::TableFormatting::format_number(@filtered_subjects.select{|s| s.send(@variable.id) == nil}.count, :count), style: 'font-weight:bold', class: 'text-muted' } ]
57
+ rows_result << unknown_row
45
58
  end
46
59
  rows_result
47
60
  end
48
-
49
61
  end
50
62
  end
51
63
  end
@@ -4,45 +4,52 @@ require 'spout/helpers/array_statistics'
4
4
  module Spout
5
5
  module Models
6
6
  module Tables
7
+ # Generates a table that displays choices versus numeric values
7
8
  class ChoicesVsNumeric < Spout::Models::Tables::Default
8
-
9
9
  def title
10
10
  "#{@variable.display_name} vs #{@chart_variable.display_name}"
11
11
  end
12
12
 
13
13
  def headers
14
14
  categories = [:quartile_one, :quartile_two, :quartile_three, :quartile_four].collect do |quartile|
15
- bucket = @filtered_both_variables_subjects.send(quartile).collect(&@chart_variable.id.to_sym)
15
+ bucket = @filtered_subjects.send(quartile).collect(&@chart_variable.id.to_sym)
16
16
  "#{bucket.min} to #{bucket.max} #{@chart_variable.units}"
17
17
  end
18
18
 
19
- [ [""] + categories + ["Total"] ]
19
+ [[''] + categories + ['Total']]
20
20
  end
21
21
 
22
22
  def footers
23
23
  total_values = [:quartile_one, :quartile_two, :quartile_three, :quartile_four].collect do |quartile|
24
- { text: Spout::Helpers::TableFormatting::format_number(@filtered_both_variables_subjects.send(quartile).count, :count), style: "font-weight:bold" }
24
+ { text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.send(quartile).count, :count), style: 'font-weight:bold' }
25
25
  end
26
26
 
27
27
  [
28
- [{ text: "Total", style: "font-weight:bold" }] + total_values + [{ text: Spout::Helpers::TableFormatting::format_number(@filtered_both_variables_subjects.count, :count), style: 'font-weight:bold'}]
28
+ [{ text: 'Total', style: 'font-weight:bold' }] + total_values + [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count, :count), style: 'font-weight:bold' }]
29
29
  ]
30
30
  end
31
31
 
32
32
  def rows
33
- filtered_both_variables_domain_options(@variable).collect do |option|
34
- row_subjects = @filtered_both_variables_subjects.select{ |s| s.send(@variable.id) == option.value }
33
+ rows_result = filtered_domain_options(@variable).collect do |option|
34
+ row_subjects = @filtered_subjects.select { |s| s.send(@variable.id) == option.value }
35
35
 
36
36
  data = [:quartile_one, :quartile_two, :quartile_three, :quartile_four].collect do |quartile|
37
- bucket = @filtered_both_variables_subjects.send(quartile).select{ |s| s.send(@variable.id) == option.value }
38
- Spout::Helpers::TableFormatting::format_number(bucket.count, :count)
37
+ count = @filtered_subjects.send(quartile).count { |s| s.send(@variable.id) == option.value }
38
+ Spout::Helpers::TableFormatting.format_number(count, :count)
39
39
  end
40
40
 
41
- [option.display_name] + data + [{ text: Spout::Helpers::TableFormatting::format_number(row_subjects.count, :count), style: 'font-weight:bold'}]
41
+ [option.display_name] + data + [{ text: Spout::Helpers::TableFormatting.format_number(row_subjects.count, :count), style: 'font-weight:bold' }]
42
42
  end
43
- end
44
-
45
43
 
44
+ if @filtered_subjects.count { |s| s.send(@variable.id).is_a?(Spout::Models::Empty) } > 0
45
+ unknown_values = [:quartile_one, :quartile_two, :quartile_three, :quartile_four].collect do |quartile|
46
+ count = @filtered_subjects.send(quartile).count { |s| s.send(@variable.id).is_a?(Spout::Models::Empty) }
47
+ { text: Spout::Helpers::TableFormatting.format_number(count, :count), class: 'text-muted' }
48
+ end
49
+ rows_result << [{ text: 'Unknown', class: 'text-muted'}] + unknown_values + [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count { |s| s.send(@variable.id).is_a?(Spout::Models::Empty) }, :count), style: 'font-weight:bold', class: 'text-muted' }]
50
+ end
51
+ rows_result
52
+ end
46
53
  end
47
54
  end
48
55
  end
@@ -5,41 +5,36 @@ module Spout
5
5
  module Models
6
6
  module Tables
7
7
  class Default
8
+ attr_reader :variable, :chart_variable, :subjects, :subtitle, :totals
8
9
 
9
- attr_reader :variable, :chart_variable, :subjects, :subtitle
10
-
11
- def initialize(variable, chart_variable, subjects, subtitle)
10
+ def initialize(variable, chart_variable, subjects, subtitle, totals)
12
11
  @variable = variable
13
12
  @chart_variable = chart_variable
14
- @subjects = subjects
15
13
  @subtitle = subtitle
16
-
17
- @filtered_subjects = @subjects.select{ |s| s.send(@chart_variable.id) != nil } rescue @filtered_subjects = []
18
- @filtered_both_variables_subjects = subjects.select{ |s| s.send(@variable.id) != nil and s.send(@chart_variable.id) != nil }.sort_by(&@chart_variable.id.to_sym) rescue @filtered_both_variables_subjects = []
19
-
20
- @values = @filtered_subjects.collect(&@variable.id.to_sym).uniq rescue @values = []
21
-
22
- @values_unique = @values.uniq
23
-
24
- @values_both_variables = @filtered_both_variables_subjects.collect(&@variable.id.to_sym).uniq rescue @values_both_variables = []
25
- @values_both_variables_unique = @values_both_variables.uniq
14
+ @totals = totals
15
+ begin
16
+ @filtered_subjects = subjects.reject { |s| s.send(@chart_variable.id).is_a?(Spout::Models::Empty) }.sort_by(&@chart_variable.id.to_sym)
17
+ rescue
18
+ @filtered_subjects = []
19
+ end
20
+ begin
21
+ @values_unique = @filtered_subjects.collect(&@variable.id.to_sym).uniq
22
+ rescue
23
+ @values_unique = []
24
+ end
26
25
  end
27
26
 
28
27
  def to_hash
29
- if valid?
30
- { title: title, subtitle: @subtitle, headers: headers, footers: footers, rows: rows }
31
- else
32
- nil
33
- end
28
+ { title: title, subtitle: @subtitle, headers: headers, footers: footers, rows: rows } if valid?
34
29
  end
35
30
 
36
31
  # TODO: Same as graphables/default.rb REFACTOR
37
32
  def valid?
38
- if @variable == nil or @chart_variable == nil or @values == []
33
+ if @variable.nil? || @chart_variable.nil? || @values_unique == []
39
34
  false
40
- elsif @variable.type == 'choices' and @variable.domain.options == []
35
+ elsif @variable.type == 'choices' && @variable.domain.options == []
41
36
  false
42
- elsif @chart_variable.type == 'choices' and @chart_variable.domain.options == []
37
+ elsif @chart_variable.type == 'choices' && @chart_variable.domain.options == []
43
38
  false
44
39
  else
45
40
  true
@@ -47,7 +42,7 @@ module Spout
47
42
  end
48
43
 
49
44
  def title
50
- ""
45
+ ''
51
46
  end
52
47
 
53
48
  def headers
@@ -62,7 +57,6 @@ module Spout
62
57
  []
63
58
  end
64
59
 
65
-
66
60
  private
67
61
 
68
62
  # Returns variable options that are either:
@@ -70,16 +64,9 @@ module Spout
70
64
  # b) or are marked as missing codes but represented in the dataset
71
65
  def filtered_domain_options(variable)
72
66
  variable.domain.options.select do |o|
73
- o.missing != true or (o.missing == true and @values_unique.include?(o.value))
67
+ o.missing != true || (o.missing == true && @values_unique.include?(o.value))
74
68
  end
75
69
  end
76
-
77
- def filtered_both_variables_domain_options(variable)
78
- variable.domain.options.select do |o|
79
- o.missing != true or (o.missing == true and @values_both_variables_unique.include?(o.value))
80
- end
81
- end
82
-
83
70
  end
84
71
  end
85
72
  end
@@ -5,42 +5,38 @@ module Spout
5
5
  module Models
6
6
  module Tables
7
7
  class NumericVsChoices < Spout::Models::Tables::Default
8
-
9
8
  def title
10
9
  "#{@chart_variable.display_name} vs #{@variable.display_name}"
11
10
  end
12
11
 
13
12
  def headers
14
- [
15
- [""] + Spout::Helpers::ArrayStatistics::calculations.collect{|calculation_label, calculation_method| calculation_label} + ["Total"]
16
- ]
13
+ [[''] + Spout::Helpers::ArrayStatistics.calculations.collect(&:first) + ['Total']]
17
14
  end
18
15
 
19
16
  def footers
20
- total_values = Spout::Helpers::ArrayStatistics::calculations.collect do |calculation_label, calculation_method, calculation_type, calculation_format|
17
+ return [] unless @totals
18
+ total_values = Spout::Helpers::ArrayStatistics.calculations.collect do |_calculation_label, calculation_method, calculation_type, calculation_format|
21
19
  total_count = @filtered_subjects.collect(&@variable.id.to_sym).send(calculation_method)
22
- { text: Spout::Helpers::TableFormatting::format_number(total_count, calculation_type, calculation_format), style: "font-weight:bold" }
20
+ { text: Spout::Helpers::TableFormatting.format_number(total_count, calculation_type, calculation_format), style: 'font-weight:bold' }
23
21
  end
24
22
 
25
23
  [
26
- [{ text: "Total", style: "font-weight:bold" }] + total_values + [{ text: Spout::Helpers::TableFormatting::format_number(@filtered_subjects.count, :count), style: 'font-weight:bold'}]
24
+ [{ text: 'Total', style: 'font-weight:bold' }] + total_values + [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count, :count), style: 'font-weight:bold' }]
27
25
  ]
28
26
  end
29
27
 
30
28
  def rows
31
29
  filtered_domain_options(@chart_variable).collect do |option|
32
- row_subjects = @filtered_subjects.select{ |s| s.send(@chart_variable.id) == option.value }
30
+ row_subjects = @filtered_subjects.select { |s| s.send(@chart_variable.id) == option.value }
33
31
 
34
- row_cells = Spout::Helpers::ArrayStatistics::calculations.collect do |calculation_label, calculation_method, calculation_type, calculation_format|
32
+ row_cells = Spout::Helpers::ArrayStatistics.calculations.collect do |_calculation_label, calculation_method, calculation_type, calculation_format|
35
33
  count = row_subjects.collect(&@variable.id.to_sym).send(calculation_method)
36
- (count == 0 && calculation_method == :count) ? { text: '-', class: 'text-muted' } : Spout::Helpers::TableFormatting::format_number(count, calculation_type, calculation_format)
34
+ (count == 0 && calculation_method == :count) ? { text: '-', class: 'text-muted' } : Spout::Helpers::TableFormatting.format_number(count, calculation_type, calculation_format)
37
35
  end
38
36
 
39
- [option.display_name] + row_cells + [{ text: Spout::Helpers::TableFormatting::format_number(row_subjects.count, :count), style: 'font-weight:bold'}]
37
+ [option.display_name] + row_cells + [{ text: Spout::Helpers::TableFormatting.format_number(row_subjects.count, :count), style: 'font-weight:bold' }]
40
38
  end
41
39
  end
42
-
43
-
44
40
  end
45
41
  end
46
42
  end
@@ -5,37 +5,36 @@ module Spout
5
5
  module Models
6
6
  module Tables
7
7
  class NumericVsNumeric < Spout::Models::Tables::Default
8
-
9
8
  def title
10
9
  "#{@chart_variable.display_name} vs #{@variable.display_name}"
11
10
  end
12
11
 
13
12
  def headers
14
- [ [""] + Spout::Helpers::ArrayStatistics::calculations.collect{|calculation_label, calculation_method| calculation_label} + ["Total"] ]
13
+ [[''] + Spout::Helpers::ArrayStatistics.calculations.collect(&:first) + ['Total']]
15
14
  end
16
15
 
17
16
  def footers
18
- total_values = Spout::Helpers::ArrayStatistics::calculations.collect do |calculation_label, calculation_method, calculation_type, calculation_format|
19
- total_count = @filtered_both_variables_subjects.collect(&@variable.id.to_sym).send(calculation_method)
20
- { text: Spout::Helpers::TableFormatting::format_number(total_count, calculation_type, calculation_format), style: "font-weight:bold" }
17
+ total_values = Spout::Helpers::ArrayStatistics.calculations.collect do |_calculation_label, calculation_method, calculation_type, calculation_format|
18
+ total_count = @filtered_subjects.collect(&@variable.id.to_sym).send(calculation_method)
19
+ { text: Spout::Helpers::TableFormatting.format_number(total_count, calculation_type, calculation_format), style: 'font-weight:bold' }
21
20
  end
22
21
 
23
22
  [
24
- [{ text: "Total", style: "font-weight:bold" }] + total_values + [{ text: Spout::Helpers::TableFormatting::format_number(@filtered_both_variables_subjects.count, :count), style: 'font-weight:bold'}]
23
+ [{ text: 'Total', style: 'font-weight:bold' }] + total_values + [{ text: Spout::Helpers::TableFormatting.format_number(@filtered_subjects.count, :count), style: 'font-weight:bold' }]
25
24
  ]
26
25
  end
27
26
 
28
27
  def rows
29
28
  [:quartile_one, :quartile_two, :quartile_three, :quartile_four].collect do |quartile|
30
- bucket = @filtered_both_variables_subjects.send(quartile)
29
+ bucket = @filtered_subjects.send(quartile)
31
30
  row_subjects = bucket.collect(&@variable.id.to_sym)
32
- data = Spout::Helpers::ArrayStatistics::calculations.collect do |calculation_label, calculation_method, calculation_type, calculation_format|
33
- Spout::Helpers::TableFormatting::format_number(row_subjects.send(calculation_method), calculation_type, calculation_format)
31
+ data = Spout::Helpers::ArrayStatistics.calculations.collect do |_calculation_label, calculation_method, calculation_type, calculation_format|
32
+ Spout::Helpers::TableFormatting.format_number(row_subjects.send(calculation_method), calculation_type, calculation_format)
34
33
  end
35
34
 
36
35
  row_name = get_row_name(quartile, bucket, row_subjects)
37
36
 
38
- [row_name] + data + [{ text: Spout::Helpers::TableFormatting::format_number(row_subjects.count, :count), style: 'font-weight:bold'}]
37
+ [row_name] + data + [{ text: Spout::Helpers::TableFormatting.format_number(row_subjects.count, :count), style: 'font-weight:bold' }]
39
38
  end
40
39
  end
41
40
 
@@ -48,7 +47,6 @@ module Spout
48
47
  "#{bucket.collect(&@chart_variable.id.to_sym).min} to #{bucket.collect(&@chart_variable.id.to_sym).max} #{@chart_variable.units}"
49
48
  end
50
49
  end
51
-
52
50
  end
53
51
  end
54
52
  end