spout 0.10.2 → 0.11.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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