chartnado 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d20a622c24b68dc7509075f867353d33152c65e1
4
- data.tar.gz: decb376a8d05741a798f5c7f1453e42dabb4a22c
3
+ metadata.gz: b20127157066903c9837361a882f6ed75b614895
4
+ data.tar.gz: 40ad1dcaeea450bddfefe6c345999b5122fa6c10
5
5
  SHA512:
6
- metadata.gz: f6dfd3ab61414c73b224eb0cb2284878366fc98869ca803fd91907528bc4ec0ab9849759183022d77064a299f1d42b42cc24f71aab4030b3687302509970b70b
7
- data.tar.gz: 89bdfe18afa1e640d104e9a2fb10dbb51faf9926496f7c4211ca0d79b07fcdd0d919e3b17284bc6278561930fa1b80dbff71bdffc61b388c50bb750acb09520c
6
+ metadata.gz: 70848f7173ba8bc4c6b2e7d754b978e767ec0b8e09a1aa8d7891609fa49c09a515a6329a7b0787f644d4c4b1c12a5ae08885f8dcd1df49f107dc141818b1f474
7
+ data.tar.gz: 2a898be78fe58e7530e3985b181f2d61f5ef315e982e8cdd921b8680661d03e037f7605fd44ce96ca657a07a31a4a095f84adba09ec2ac966e290c6d94986343
data/README.md CHANGED
@@ -10,12 +10,14 @@ In your controller, add the following to tell the controller to respond to json
10
10
  include Chartnado
11
11
  ```
12
12
 
13
- Then in your views, now in your views, you can write an expression to show the average tasks completed per today relative to total tasks:
13
+ Then in your views, you can write an expression to show the average tasks completed per today relative to total tasks like this:
14
14
 
15
15
  ```ruby
16
16
  <%= line_chart { Task.group_by_day(:completed_at).count / Task.count } %>
17
17
  ```
18
18
 
19
+ See the demo of chartkick-remote and Chartnado at http://chartkick-remote-demo.heroku.com.
20
+
19
21
  ## Totals
20
22
 
21
23
  By default chartnado adds totals to pie and stacked area charts using some hacky settings for google charts. To get the total to appear, you need to use the chartnado version of the chartkick javascript called `chartkick-chartnado.js` instead of `chartkick.js`. If you are including the javascript in sprockets manifest file, this:
@@ -21,8 +21,9 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency "activesupport", '>= 3'
23
23
  spec.add_dependency "chartkick", '>= 1.0'
24
- spec.add_dependency "chartkick-remote", '>= 1.2'
24
+ spec.add_dependency "chartkick-remote", '>= 1.3'
25
25
  spec.add_dependency "railties", ">= 3.1"
26
+ spec.add_development_dependency "responders", '~> 2.0'
26
27
  spec.add_development_dependency "bundler", '~> 1.3'
27
28
  spec.add_development_dependency "rake", '~> 10.3'
28
29
  spec.add_development_dependency "rspec", '~> 3.0'
@@ -14,7 +14,12 @@ module Chartnado::Helpers
14
14
  new_options = chartkick_options.reverse_merge(
15
15
  stacked: true,
16
16
  library: {
17
- focusTarget: 'category',
17
+ focusTarget: 'category'
18
+ }
19
+ )
20
+ new_json_options = json_options.reverse_merge(show_total: true, reverse_sort: true)
21
+ new_options.reverse_merge!(
22
+ library: {
18
23
  series: {
19
24
  0 => {
20
25
  lineWidth: 0,
@@ -23,9 +28,29 @@ module Chartnado::Helpers
23
28
  }
24
29
  }
25
30
  }
26
- )
31
+ ) if new_json_options[:show_total]
27
32
  area_chart_without_chartnado(**new_options) do
28
- data_block.call(json_options.reverse_merge(show_total: true, reverse_sort: true))
33
+ data_block.call(new_json_options)
34
+ end
35
+ end.render(*args, **options)
36
+ end
37
+
38
+ def pie_chart_with_chartnado(*args, **options, &block)
39
+ Chartnado::Renderer.new(self, block) do |chartkick_options, json_options, data_block|
40
+ new_json_options = json_options.reverse_merge(show_total: true)
41
+ new_options = chartkick_options.reverse_merge!(
42
+ library: {
43
+ series: {
44
+ 0 => {
45
+ lineWidth: 0,
46
+ pointSize: 0,
47
+ visibleInLegend: false
48
+ }
49
+ }
50
+ }
51
+ ) if new_json_options[:show_total]
52
+ pie_chart_without_chartnado(**new_options) do
53
+ data_block.call(new_json_options)
29
54
  end
30
55
  end.render(*args, **options)
31
56
  end
@@ -11,7 +11,7 @@ class Chartnado::Renderer
11
11
 
12
12
  delegate :controller, to: :context
13
13
 
14
- def render(*args, **options)
14
+ def render(*args, ** options)
15
15
  json_options = {}
16
16
  chartkick_options = options.dup
17
17
 
@@ -40,40 +40,42 @@ class Chartnado::Renderer
40
40
  }
41
41
 
42
42
  if options[:wrapper_proc]
43
- context.instance_exec(*args, renderer, **options, &options[:wrapper_proc])
43
+ context.instance_exec(*args, renderer, ** options, &options[:wrapper_proc])
44
44
  else
45
45
  renderer.call
46
46
  end
47
47
  end
48
48
 
49
49
  def chart_json(series, show_total: false, reverse_sort: false, percentage: false)
50
- series = series_product(100.0, series) if percentage
51
- if series.is_a?(Hash)
52
- if (key = series.keys.first) and key.is_a?(Array) and key.size == 2
50
+ series = Chartnado::Series::Wrap[series]
51
+ series *= 100.0 if percentage
52
+ if series.has_separate_named_series?
53
+ series = series.to_a
54
+ if series.first.second.respond_to?(:map)
53
55
  totals = Hash.new(0.0)
54
- new_series = series.group_by{|k, v| k[0] }.sort_by { |k| k.to_s }
56
+ new_series = series.sort_by { |item| item.first.to_s }
55
57
  new_series = new_series.reverse if reverse_sort
56
58
 
57
59
  new_series = new_series.map do |name, data|
58
60
  {
59
61
  name: name,
60
62
  data: data.map do |k, v|
61
- totals[k[1]] += v if show_total
62
- [k[1], v]
63
+ totals[k] += v if show_total
64
+ [k, v]
63
65
  end
64
66
  }
65
67
  end
66
68
 
67
69
  if show_total
68
70
  [{name: 'Total',
69
- data: totals.map {|k,v| [k, 0] },
70
- tooltip: totals.map {|k,v| [k, v] }
71
+ data: totals.map { |k, v| [k, 0] },
72
+ tooltip: totals.map { |k, v| [k, v] }
71
73
  }] + new_series
72
74
  else
73
75
  new_series
74
76
  end
75
77
  else
76
- new_series = series.sort_by { |key| key.to_s }
78
+ new_series = series.sort_by { |item| item.first.to_s }
77
79
  new_series = new_series.reverse if reverse_sort
78
80
 
79
81
  if show_total
@@ -82,32 +84,32 @@ class Chartnado::Renderer
82
84
  new_series
83
85
  end
84
86
  end
85
- elsif series.is_a?(Array) && series.first.is_a?(Array)
86
- if series.first.second.respond_to?(:map)
87
+ elsif series.hash?
88
+ if (key = series.keys.first) and key.is_a?(Array) and key.size == 2
87
89
  totals = Hash.new(0.0)
88
- new_series = series.sort_by { |item| item.first.to_s }
90
+ new_series = series.group_by { |k, v| k[0] }.sort_by { |k| k.to_s }
89
91
  new_series = new_series.reverse if reverse_sort
90
92
 
91
93
  new_series = new_series.map do |name, data|
92
94
  {
93
95
  name: name,
94
96
  data: data.map do |k, v|
95
- totals[k] += v if show_total
96
- [k, v]
97
+ totals[k[1]] += v if show_total
98
+ [k[1], v]
97
99
  end
98
100
  }
99
101
  end
100
102
 
101
103
  if show_total
102
104
  [{name: 'Total',
103
- data: totals.map {|k,v| [k, 0] },
104
- tooltip: totals.map {|k,v| [k, v] }
105
+ data: totals.map { |k, v| [k, 0] },
106
+ tooltip: totals.map { |k, v| [k, v] }
105
107
  }] + new_series
106
108
  else
107
109
  new_series
108
110
  end
109
111
  else
110
- new_series = series.sort_by { |item| item.first.to_s }
112
+ new_series = series.sort_by { |key| key.to_s }
111
113
  new_series = new_series.reverse if reverse_sort
112
114
 
113
115
  if show_total
@@ -116,12 +118,10 @@ class Chartnado::Renderer
116
118
  new_series
117
119
  end
118
120
  end
121
+ elsif series.respond_to?(:map)
122
+ series
119
123
  else
120
- if series.respond_to?(:map)
121
- series
122
- else
123
- [['Total', series]]
124
- end
124
+ [['Total', series]]
125
125
  end
126
126
  end
127
127
  end
@@ -1,4 +1,7 @@
1
+ require 'active_support/dependencies/autoload'
2
+ require 'active_support/deprecation'
1
3
  require 'active_support/core_ext'
4
+ require 'chartnado/series/wrap'
2
5
 
3
6
  module Chartnado
4
7
  module Series
@@ -9,35 +12,7 @@ module Chartnado
9
12
  #
10
13
  # @return [Series/Multiple-Series]
11
14
  def series_product(val, series, precision: 2)
12
- if dimensions(val) > dimensions(series)
13
- return series_product(series, val)
14
- end
15
-
16
- return with_precision(precision, val.to_f * series.to_f) unless series.respond_to?(:length)
17
- return series unless series.length > 0
18
-
19
- if is_an_array_of_named_series?(series) || series.is_a?(Array) && series.first.is_a?(Array)
20
- series.map { |(name, data)| [name, series_product(val, data)] }
21
- elsif series.is_a?(Hash)
22
- series.to_a.reduce({}) do |hash, (key, value)|
23
- if val.is_a?(Hash)
24
- if key.is_a?(Array)
25
- scalar = val[key.second]
26
- else
27
- scalar = val[key]
28
- end
29
- else
30
- scalar = val
31
- end
32
- scalar ||= 0
33
- hash[key] = scalar * value
34
- hash
35
- end
36
- else
37
- series.map do |value|
38
- val * value
39
- end
40
- end
15
+ Wrap[series].times(val, precision: precision)
41
16
  end
42
17
 
43
18
  # @api public
@@ -46,46 +21,8 @@ module Chartnado
46
21
  #
47
22
  # @return [Series/Multiple-Series]
48
23
  def series_ratio(top_series, bottom_series, multiplier: 1.0, precision: 2)
49
- if bottom_series.is_a?(Numeric)
50
- return series_product(1.0 * multiplier / bottom_series, top_series, precision: precision)
51
- end
52
- if has_multiple_series?(top_series) && !has_multiple_series?(bottom_series)
53
- top_series_by_name = data_by_name(top_series)
54
- if is_an_array_of_named_series?(top_series)
55
- top_series_by_name.map do |name, top_values|
56
- [
57
- name,
58
- series_ratio(top_values, bottom_series, multiplier: multiplier, precision: precision)
59
- ]
60
- end
61
- else
62
- bottom_series.reduce({}) do |hash, (key, value)|
63
- top_series_by_name.keys.each do |name|
64
- top_key = [name, *key]
65
- top_value = top_series_by_name[name][top_key]
66
- if top_value
67
- hash[top_key] = series_ratio(top_value, value, multiplier: multiplier, precision: precision)
68
- end
69
- end
70
- hash
71
- end
72
- end
73
- elsif is_an_array_of_named_series?(bottom_series)
74
- top_series_by_name = data_by_name(top_series)
75
- bottom_series.map do |(name, data)|
76
- [
77
- name,
78
- series_ratio(top_series_by_name[name], data, multiplier: multiplier, precision: precision)
79
- ]
80
- end
81
- elsif bottom_series.respond_to?(:reduce)
82
- bottom_series.reduce({}) do |hash, (key, value)|
83
- hash[key] = series_ratio(top_series[key] || 0, value, multiplier: multiplier, precision: precision)
84
- hash
85
- end
86
- else
87
- with_precision(precision, top_series.to_f * multiplier.to_f / bottom_series.to_f)
88
- end
24
+ Wrap[top_series].
25
+ over(bottom_series, multiplier: multiplier, precision: precision)
89
26
  end
90
27
 
91
28
  # @api public
@@ -98,34 +35,7 @@ module Chartnado
98
35
  #
99
36
  # @return [Series/Multiple-Series/Scalar]
100
37
  def series_sum(*series, scalar_sum: 0.0)
101
- return [] unless series.length > 0
102
-
103
- (series, scalars) = series.partition { |s| s.respond_to?(:map) }
104
- scalar_sum += scalars.reduce(:+) || 0.0
105
-
106
- if series.first.is_a?(Hash)
107
- keys = series.map(&:keys).flatten(1).uniq
108
- keys.reduce({}) do |hash, key|
109
- hash[key] = (series.map { |s| s[key] }.compact.reduce(:+) || 0) + scalar_sum
110
- hash
111
- end
112
- elsif is_an_array_of_named_series?(series.first)
113
- series.flatten(1).group_by(&:first).map do |name, values|
114
- data = values.map(&:second).reduce(Hash.new(scalar_sum)) do |hash, values|
115
- values.each do |key, value|
116
- hash[key] += value
117
- end
118
- hash
119
- end
120
- [
121
- name, data
122
- ]
123
- end
124
- elsif series.first.is_a?(Array)
125
- series.map { |s| s.reduce(:+) + scalar_sum }
126
- else
127
- scalar_sum
128
- end
38
+ Wrap[series.shift].add(*series, scalar_sum: scalar_sum)
129
39
  end
130
40
 
131
41
  # @api public
@@ -139,48 +49,5 @@ module Chartnado
139
49
  len = sorted.length
140
50
  (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
141
51
  end
142
-
143
- private
144
-
145
- def data_by_name(series)
146
- if is_an_array_of_named_series?(series)
147
- series.reduce({}) do |hash, value|
148
- hash[value.first] = value.second
149
- hash
150
- end
151
- else
152
- series.reduce({}) do |hash, (key, value)|
153
- new_key = Array.wrap(key.first).first
154
- hash[new_key] = {key => value }
155
- hash
156
- end
157
- end
158
- end
159
-
160
- def series_names(series)
161
- series.map { |key| key.first }.uniq
162
- end
163
-
164
- def has_multiple_series?(series)
165
- is_an_array_of_named_series?(series) || series.is_a?(Hash) && series.first && series.first[0].is_a?(Array) && series.first[0].length > 1
166
- end
167
-
168
- def is_an_array_of_named_series?(series)
169
- series.is_a?(Array) && series.first.second.is_a?(Hash)
170
- end
171
-
172
- def dimensions(series)
173
- return 1 unless series.respond_to?(:length)
174
- if series.first && series.first.is_a?(Array)
175
- 3
176
- else
177
- 2
178
- end
179
- end
180
-
181
- def with_precision(precision, value)
182
- value = value.round(precision) if precision
183
- value
184
- end
185
52
  end
186
53
  end
@@ -0,0 +1,201 @@
1
+ module Chartnado
2
+ module Series
3
+ class Wrap < SimpleDelegator
4
+ def self.[](series)
5
+ series.class == self ? series : new(series)
6
+ end
7
+
8
+ def *(val)
9
+ times(val, precision: nil)
10
+ end
11
+
12
+ def times(factor, precision: 2)
13
+ factor = wrap(factor)
14
+
15
+ return factor.times(self, precision: precision) if factor.dimensions > dimensions
16
+ return with_precision(precision, factor.to_f * to_f) unless dimensions > 1
17
+ return self unless length > 0
18
+
19
+ if has_separate_named_series? || array? && first.is_a?(Array)
20
+ result = map { |(name, data)| [name, wrap(data) * factor] }
21
+ elsif hash?
22
+ result = to_a.reduce({}) do |hash, (key, value)|
23
+ if factor.hash?
24
+ if key.is_a?(Array)
25
+ scalar = factor[key.second]
26
+ else
27
+ scalar = factor[key]
28
+ end
29
+ else
30
+ scalar = factor
31
+ end
32
+ scalar ||= 0
33
+ hash[key] = scalar * value
34
+ hash
35
+ end
36
+ else
37
+ result = map do |value|
38
+ factor * value
39
+ end
40
+ end
41
+
42
+ wrap(result)
43
+ end
44
+
45
+ def add(*series, scalar_sum: 0.0)
46
+ (series, scalars) = [__getobj__, *series].partition { |s| s.respond_to?(:map) }
47
+ scalar_sum += scalars.reduce(:+) || 0.0
48
+ return wrap(scalar_sum) unless series.present?
49
+
50
+ if wrap(series.first).has_separate_named_series?
51
+ result = series.map(&:to_a).flatten(1).group_by(&:first).map do |name, values|
52
+ data = values.map(&:second).reduce(Hash.new(scalar_sum)) do |hash, values|
53
+ values.each do |key, value|
54
+ hash[key] += value
55
+ end
56
+ hash
57
+ end
58
+ [
59
+ name, data
60
+ ]
61
+ end
62
+ elsif series.first.is_a?(Hash)
63
+ keys = series.flat_map(&:keys).uniq
64
+ result = keys.reduce({}) do |hash, key|
65
+ hash[key] = (series.map { |s| s[key] }.compact.reduce(:+) || 0) + scalar_sum
66
+ hash
67
+ end
68
+ elsif series.first.is_a?(Array)
69
+ result = series.map { |s| s.reduce(:+) + scalar_sum }
70
+ else
71
+ result = scalar_sum
72
+ end
73
+
74
+ wrap(result)
75
+ end
76
+
77
+ def over(bottom, multiplier: 1.0, precision: 2)
78
+ bottom = wrap(bottom)
79
+ return times(1.0 * multiplier / bottom, precision: precision) if bottom.dimensions == 1
80
+
81
+ if dimensions > bottom.dimensions
82
+ top_series_by_name = data_by_name
83
+ if has_separate_named_series?
84
+ data_by_name.map do |name, top_values|
85
+ [
86
+ name,
87
+ wrap(top_values).
88
+ over(bottom, multiplier: multiplier, precision: precision)
89
+ ]
90
+ end
91
+ else
92
+ bottom.reduce({}) do |hash, (key, value)|
93
+ top_series_by_name.keys.each do |name|
94
+ top_key = [name, *Array.wrap(key)]
95
+ top_value = top_series_by_name[name][top_key]
96
+ if top_value
97
+ hash[top_key] = wrap(top_value).
98
+ over(value, multiplier: multiplier, precision: precision)
99
+ end
100
+ end
101
+ hash
102
+ end
103
+ end
104
+ elsif array_of_named_series?
105
+ top_series_by_name = data_by_name
106
+ bottom.map do |(name, data)|
107
+ [
108
+ name,
109
+ wrap(top_series_by_name[name]).
110
+ over(data, multiplier: multiplier, precision: precision)
111
+ ]
112
+ end
113
+ elsif bottom.respond_to?(:reduce)
114
+ bottom.reduce({}) do |hash, (key, value)|
115
+ hash[key] = wrap(self[key] || 0).
116
+ over(value, multiplier: multiplier, precision: precision)
117
+ hash
118
+ end
119
+ else
120
+ with_precision(precision, to_f * multiplier.to_f / bottom.to_f)
121
+ end
122
+ end
123
+
124
+ def has_multiple_series?
125
+ array_of_named_series? || is_a?(Hash) && begin
126
+ first_series = series.first
127
+ first_series[0].is_a?(Array) && first_series[0].length > 1 || first_series[1].respond_to?(:length)
128
+ end
129
+ end
130
+
131
+ def hash?
132
+ __getobj__.is_a?(Hash)
133
+ end
134
+
135
+ def array?
136
+ __getobj__.is_a?(Array)
137
+ end
138
+
139
+ def array_of_named_series?
140
+ array? && first.second.is_a?(Hash)
141
+ end
142
+
143
+ def hash_of_named_series?
144
+ hash? && values.first && values.first.is_a?(Hash)
145
+ end
146
+
147
+ def dimensions
148
+ return 1 unless respond_to?(:length)
149
+ if hash?
150
+ if keys.first && keys.first.is_a?(Array) || hash_of_named_series?
151
+ 3
152
+ else
153
+ 2
154
+ end
155
+ else
156
+ if first && first.is_a?(Array)
157
+ 3
158
+ else
159
+ 2
160
+ end
161
+ end
162
+ end
163
+
164
+ def has_separate_named_series?
165
+ hash_of_named_series? || array_of_named_series?
166
+ end
167
+
168
+ private
169
+
170
+ def data_by_name
171
+ return self if hash_of_named_series?
172
+ result = if array_of_named_series?
173
+ reduce({}) do |hash, (name, values)|
174
+ hash[name] = values
175
+ hash
176
+ end
177
+ else
178
+ hash = Hash.new { |hash, key| hash[key] = {} }
179
+ x = reduce(hash) do |hash, (key, value)|
180
+ p key.first
181
+ new_key = Array.wrap(key.first).first
182
+ hash[new_key][key] = value
183
+ hash
184
+ end
185
+ p x
186
+ x
187
+ end
188
+ wrap(result)
189
+ end
190
+
191
+ def with_precision(precision, value)
192
+ value = value.round(precision) if precision
193
+ value
194
+ end
195
+
196
+ def wrap(val)
197
+ self.class[val]
198
+ end
199
+ end
200
+ end
201
+ end
@@ -1,3 +1,3 @@
1
1
  module Chartnado
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,3 +1,4 @@
1
+ require 'responders'
1
2
  require 'action_controller'
2
3
  require 'action_view'
3
4
 
@@ -17,6 +17,12 @@ describe Chartnado::Renderer do
17
17
  {name: :a, data: [[1, 10]]},
18
18
  {name: :b, data: [[1, 20]]}]
19
19
  end
20
+ it "can add multiply by 100 to create a percentage" do
21
+ expect(chart_json({[:a, 1] => 0.1, [:b, 1] => 0.2}, percentage: true, show_total: true)).
22
+ to eq [{name: 'Total', data: [[1, 0]], tooltip: [[1, 30.0]]},
23
+ {name: :a, data: [[1, 10.0]]},
24
+ {name: :b, data: [[1, 20.0]]}]
25
+ end
20
26
  describe "with multiple scalar series" do
21
27
  it "can handle scalars" do
22
28
  expect(chart_json({:a => 10, :b => 20})).
@@ -40,6 +46,18 @@ describe Chartnado::Renderer do
40
46
  {name: :b, data: [[1, 20]]}]
41
47
  end
42
48
  end
49
+ describe "for multiple series organized as a hash" do
50
+ it "can generate chartkick compatible series" do
51
+ expect(chart_json({:a => {1 => 10}, :b => {1 => 20}})).
52
+ to eq [{name: :a, data: [[1, 10]]}, {name: :b, data: [[1,20]]}]
53
+ end
54
+ it "can add totals" do
55
+ expect(chart_json({:a => {1 => 10}, :b => {1 => 20}}, show_total: true)).
56
+ to eq [{name: 'Total', data: [[1, 0]], tooltip: [[1, 30.0]]},
57
+ {name: :a, data: [[1, 10]]},
58
+ {name: :b, data: [[1, 20]]}]
59
+ end
60
+ end
43
61
  describe "for data that is just a scalar" do
44
62
  it "shows the scalar as the total" do
45
63
  expect(chart_json(10)).
@@ -66,6 +66,16 @@ describe Chartnado::Series do
66
66
  expect(series_sum(2,[[:a, {0 => 3}]])).to eq ([[:a, {0 => 5}]])
67
67
  end
68
68
  end
69
+ describe "adding a scalar to an hash of named series" do
70
+ it "returns each item of the array with a scalar added" do
71
+ expect(series_sum(2,{'a' => {0 => 3}})).to eq ([['a', {0 => 5}]])
72
+ end
73
+ end
74
+ describe "adding a scalar to a hash with 2 dimensional keys" do
75
+ it "returns each item of the array with a scalar added" do
76
+ expect(series_sum({['a', 0] => 3}, 1)).to eq ({['a', 0] => 4})
77
+ end
78
+ end
69
79
  describe "adding two hashes" do
70
80
  it "returns each item of the array with a scalar added" do
71
81
  expect(series_sum({0 => 1},{0 => 2})).to eq ({0 => 3})
@@ -76,6 +86,11 @@ describe Chartnado::Series do
76
86
  expect(series_sum({0 => 1},{0 => 2}, 5)).to eq ({0 => 8})
77
87
  end
78
88
  end
89
+ describe "adding nothing but a scalar sum" do
90
+ it "returns the scalar sum" do
91
+ expect(series_sum(scalar_sum: 2)).to eq 2
92
+ end
93
+ end
79
94
  end
80
95
 
81
96
  describe "#series_ratio" do
@@ -103,8 +118,16 @@ describe Chartnado::Series do
103
118
  end
104
119
  describe "ratio of a named series to a non-named series" do
105
120
  it "returns the ratio" do
106
- expect(series_ratio({[:series_a, 0] => 1},
107
- {0 => 2})).to eq ({[:series_a, 0] => 0.5})
121
+ expect(series_ratio({[:series_a, 0] => 1, [:series_a, 1] => 3},
122
+ {0 => 2, 1 => 4})).to eq ({[:series_a, 0] => 0.5, [:series_a, 1] => 0.75})
123
+ end
124
+ describe "when the keys are time values" do
125
+ let(:t1) { Time.parse('2014-09-15 07:00:00 UTC') }
126
+ let(:t2) { Time.parse('2014-09-22 07:00:00 UTC') }
127
+ it "still returns the ratio" do
128
+ expect(series_ratio({[:series_a, t1] => 1, [:series_a, t2] => 3},
129
+ {t1 => 2, t2 => 4})).to eq ({[:series_a, t1] => 0.5, [:series_a, t2] => 0.75})
130
+ end
108
131
  end
109
132
  end
110
133
  describe "ratio of an array of named series to a non-named series" do
@@ -113,8 +136,15 @@ describe Chartnado::Series do
113
136
  {0 => 2})).to eq [[:series_a, {0 => 0.5}]]
114
137
  end
115
138
  end
139
+ describe "ratio of a hash of named series to a non-named series" do
140
+ it "returns the ratio" do
141
+ expect(series_ratio({:series_a => {0 => 1}},
142
+ {0 => 2})).to eq [[:series_a, {0 => 0.5}]]
143
+ end
144
+ end
145
+
116
146
  describe "ratio of a series to a scalar" do
117
- xit "returns the ratio" do
147
+ it "returns the ratio" do
118
148
  expect(series_ratio({0 => 1}, 2)).to eq ({0 => 0.5})
119
149
  end
120
150
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chartnado
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew S. Brown
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-25 00:00:00.000000000 Z
11
+ date: 2015-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '1.2'
47
+ version: '1.3'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '1.2'
54
+ version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: railties
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: responders
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +234,7 @@ files:
220
234
  - lib/chartnado/helpers/series_helper.rb
221
235
  - lib/chartnado/renderer.rb
222
236
  - lib/chartnado/series.rb
237
+ - lib/chartnado/series/wrap.rb
223
238
  - lib/chartnado/version.rb
224
239
  - spec/controllers/controller_spec.rb
225
240
  - spec/dsl_spec.rb
@@ -249,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
264
  version: '0'
250
265
  requirements: []
251
266
  rubyforge_project:
252
- rubygems_version: 2.2.2
267
+ rubygems_version: 2.4.6
253
268
  signing_key:
254
269
  specification_version: 4
255
270
  summary: Chartkick charts with extras