apexcharts 0.1.1
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.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +132 -0
- data/lib/apexcharts/charts/area.rb +7 -0
- data/lib/apexcharts/charts/bar.rb +11 -0
- data/lib/apexcharts/charts/capabilities/annotations.rb +75 -0
- data/lib/apexcharts/charts/cartesian.rb +60 -0
- data/lib/apexcharts/charts/column.rb +7 -0
- data/lib/apexcharts/charts/line.rb +7 -0
- data/lib/apexcharts/charts/mixed.rb +72 -0
- data/lib/apexcharts/charts/scatter.rb +7 -0
- data/lib/apexcharts/charts/syncing.rb +61 -0
- data/lib/apexcharts/charts.rb +8 -0
- data/lib/apexcharts/helper.rb +66 -0
- data/lib/apexcharts/options/annotations.rb +10 -0
- data/lib/apexcharts/options/axis.rb +17 -0
- data/lib/apexcharts/options/chart.rb +24 -0
- data/lib/apexcharts/options/data_labels.rb +12 -0
- data/lib/apexcharts/options/div_attributes.rb +10 -0
- data/lib/apexcharts/options/fill.rb +12 -0
- data/lib/apexcharts/options/grid.rb +15 -0
- data/lib/apexcharts/options/legend.rb +24 -0
- data/lib/apexcharts/options/markers.rb +18 -0
- data/lib/apexcharts/options/no_data.rb +12 -0
- data/lib/apexcharts/options/plot_options.rb +11 -0
- data/lib/apexcharts/options/root.rb +41 -0
- data/lib/apexcharts/options/states.rb +9 -0
- data/lib/apexcharts/options/stroke.rb +12 -0
- data/lib/apexcharts/options/subtitle.rb +7 -0
- data/lib/apexcharts/options/theme.rb +8 -0
- data/lib/apexcharts/options/title.rb +13 -0
- data/lib/apexcharts/options/tooltip.rb +22 -0
- data/lib/apexcharts/options/x_axis.rb +12 -0
- data/lib/apexcharts/options/y_axis.rb +15 -0
- data/lib/apexcharts/options_builder.rb +320 -0
- data/lib/apexcharts/series/cartesian.rb +24 -0
- data/lib/apexcharts/series.rb +1 -0
- data/lib/apexcharts/support/rails.rb +9 -0
- data/lib/apexcharts/utils/date_time.rb +60 -0
- data/lib/apexcharts/utils/hash.rb +31 -0
- data/lib/apexcharts/utils.rb +2 -0
- data/lib/apexcharts/version.rb +3 -0
- data/lib/apexcharts.rb +2 -0
- data/vendor/assets/javascripts/apexcharts.js +6 -0
- metadata +157 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module Apexcharts
|
2
|
+
class LegendOptions < ::SmartKv
|
3
|
+
optional *%i[
|
4
|
+
container_margin containerMargin
|
5
|
+
floating
|
6
|
+
font_family fontFamily
|
7
|
+
font_size fontSize
|
8
|
+
formatter
|
9
|
+
horizontal_align horizontalAlign
|
10
|
+
item_margin itemMargin
|
11
|
+
labels
|
12
|
+
markers
|
13
|
+
offset_x offsetX
|
14
|
+
offset_y offsetY
|
15
|
+
on_item_click onItemClick
|
16
|
+
on_item_hover onItemHover
|
17
|
+
position
|
18
|
+
show
|
19
|
+
show_for_single_series showForSingleSeries
|
20
|
+
text_anchor textAnchor
|
21
|
+
vertical_align verticalAlign
|
22
|
+
]
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Apexcharts
|
2
|
+
class MarkersOptions < ::SmartKv
|
3
|
+
optional *%i[
|
4
|
+
colors
|
5
|
+
discrete
|
6
|
+
fill_opacity fillOpacity
|
7
|
+
hover
|
8
|
+
offset_x offsetX
|
9
|
+
offset_y offsetY
|
10
|
+
radius
|
11
|
+
shape
|
12
|
+
size
|
13
|
+
stroke_color strokeColor
|
14
|
+
stroke_opacity strokeOpacity
|
15
|
+
stroke_width strokeWidth
|
16
|
+
]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'div_attributes'
|
2
|
+
require_relative 'chart'
|
3
|
+
require_relative 'stroke'
|
4
|
+
require_relative 'states'
|
5
|
+
|
6
|
+
module Apexcharts
|
7
|
+
class RootOptions < ::SmartKv
|
8
|
+
optional *%i[
|
9
|
+
annotations
|
10
|
+
chart
|
11
|
+
chart_id
|
12
|
+
colors
|
13
|
+
data_labels dataLabels
|
14
|
+
fill
|
15
|
+
grid
|
16
|
+
group
|
17
|
+
labels
|
18
|
+
legend
|
19
|
+
markers
|
20
|
+
no_data noData
|
21
|
+
plot_options plotOptions
|
22
|
+
responsive
|
23
|
+
series
|
24
|
+
states
|
25
|
+
stroke
|
26
|
+
subtitle
|
27
|
+
theme
|
28
|
+
title
|
29
|
+
tooltip
|
30
|
+
var
|
31
|
+
xaxis
|
32
|
+
xtitle
|
33
|
+
yaxis
|
34
|
+
ytitle
|
35
|
+
],
|
36
|
+
*DivAttributes.optional_keys,
|
37
|
+
*ChartOptions.optional_keys,
|
38
|
+
*StrokeOptions.optional_keys,
|
39
|
+
*StatesOptions.optional_keys
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Apexcharts
|
2
|
+
class TooltipOptions < ::SmartKv
|
3
|
+
optional *%i[
|
4
|
+
custom
|
5
|
+
enabled
|
6
|
+
fill_series_color fillSeriesColor
|
7
|
+
fixed
|
8
|
+
follow_cursor followCursor
|
9
|
+
intersect
|
10
|
+
inverse_order inverseOrder
|
11
|
+
items
|
12
|
+
marker
|
13
|
+
on_dataset_hover onDatasetHover
|
14
|
+
shared
|
15
|
+
style
|
16
|
+
theme
|
17
|
+
x
|
18
|
+
y
|
19
|
+
z
|
20
|
+
]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'axis'
|
2
|
+
|
3
|
+
module Apexcharts
|
4
|
+
class YAxisOptions < AxisOptions
|
5
|
+
optional *%i[
|
6
|
+
decimals_in_float decimalsInFloat
|
7
|
+
force_nice_scale forceNiceScale
|
8
|
+
logarithmic
|
9
|
+
opposite
|
10
|
+
series_name seriesName
|
11
|
+
show
|
12
|
+
show_always showAlways
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,320 @@
|
|
1
|
+
require 'smart_kv'
|
2
|
+
require_relative 'options/root'
|
3
|
+
require_relative 'options/annotations'
|
4
|
+
require_relative 'options/data_labels'
|
5
|
+
require_relative 'options/fill'
|
6
|
+
require_relative 'options/grid'
|
7
|
+
require_relative 'options/legend'
|
8
|
+
require_relative 'options/markers'
|
9
|
+
require_relative 'options/no_data'
|
10
|
+
require_relative 'options/plot_options'
|
11
|
+
require_relative 'options/states'
|
12
|
+
require_relative 'options/subtitle'
|
13
|
+
require_relative 'options/theme'
|
14
|
+
require_relative 'options/tooltip'
|
15
|
+
require_relative 'options/x_axis'
|
16
|
+
require_relative 'options/y_axis'
|
17
|
+
|
18
|
+
module Apexcharts
|
19
|
+
class OptionsBuilder
|
20
|
+
THEME_PALETTES = ["palette1", "palette2", "palette3", "palette4", "palette5",
|
21
|
+
"palette6", "palette7", "palette8", "palette9", "palette10"]
|
22
|
+
|
23
|
+
attr_reader :built
|
24
|
+
|
25
|
+
def initialize(x_sample, options)
|
26
|
+
@options = options
|
27
|
+
@xtype = Utils::DateTime.xtype(x_sample)
|
28
|
+
@built = {}
|
29
|
+
build_options
|
30
|
+
@built.compact!
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_options
|
34
|
+
RootOptions.check @options
|
35
|
+
|
36
|
+
build_chart
|
37
|
+
build_div
|
38
|
+
build_annotations
|
39
|
+
build_data_labels
|
40
|
+
build_fill
|
41
|
+
build_grid
|
42
|
+
build_labels
|
43
|
+
build_legend
|
44
|
+
build_markers
|
45
|
+
build_no_data
|
46
|
+
build_plot_options
|
47
|
+
build_responsive
|
48
|
+
build_states
|
49
|
+
build_stroke
|
50
|
+
build_subtitle
|
51
|
+
build_theme
|
52
|
+
build_title
|
53
|
+
build_tooltip
|
54
|
+
build_xaxis
|
55
|
+
build_yaxis
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_div
|
59
|
+
@built[:div] = {
|
60
|
+
id: @options.delete(:id),
|
61
|
+
var: @options.delete(:var),
|
62
|
+
class: @options.delete(:class),
|
63
|
+
style: @options.delete(:style)
|
64
|
+
}.compact
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_annotations
|
68
|
+
annotations = @options.delete :annotations
|
69
|
+
@built[:annotations] = if annotations.is_a? Hash
|
70
|
+
AnnotationsOptions.check annotations.compact
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def build_chart
|
75
|
+
@built[:chart] = {
|
76
|
+
id: @options[:chart_id] || @options[:id],
|
77
|
+
group: @options.delete(:group),
|
78
|
+
height: @options.delete(:height) { 400 },
|
79
|
+
width: @options.delete(:width),
|
80
|
+
stacked: @options.delete(:stacked),
|
81
|
+
animations: enabled(@options.delete(:animations)),
|
82
|
+
sparkline: enabled(@options.delete(:sparkline)),
|
83
|
+
background: @options.delete(:background),
|
84
|
+
fore_color: @options.delete(:fore_color) do
|
85
|
+
@options.delete(:foreColor)
|
86
|
+
end
|
87
|
+
}.compact
|
88
|
+
|
89
|
+
chart = @options.delete :chart
|
90
|
+
if chart.is_a? Hash
|
91
|
+
@built[:chart].merge! ChartOptions.check(chart.compact)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def build_data_labels
|
96
|
+
data_labels = @options.delete :data_labels do
|
97
|
+
@options.delete :dataLabels
|
98
|
+
end
|
99
|
+
return if data_labels.nil?
|
100
|
+
@built[:data_labels] = if [true, false].include? data_labels
|
101
|
+
{enabled: data_labels}
|
102
|
+
elsif options.is_a? Hash
|
103
|
+
DataLabelsOptions.check options.compact
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def build_fill
|
108
|
+
fill = @options.delete :fill
|
109
|
+
@built[:fill] = if fill.is_a? String
|
110
|
+
{type: fill}
|
111
|
+
elsif fill.is_a? Hash
|
112
|
+
FillOptions.check fill.compact
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def build_grid
|
117
|
+
grid = @options.delete :grid
|
118
|
+
@built[:grid] = if [true, false].include? grid
|
119
|
+
{show: grid}
|
120
|
+
elsif grid.is_a? Hash
|
121
|
+
GridOptions.check grid.compact
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def build_labels
|
126
|
+
labels = @options.delete :labels
|
127
|
+
@built[:labels] = if labels.nil?
|
128
|
+
elsif labels.is_a? Array
|
129
|
+
labels
|
130
|
+
else
|
131
|
+
[labels]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def build_legend
|
136
|
+
labels = @options.delete :labels
|
137
|
+
@built[:legend] = if [true, false].include? labels
|
138
|
+
{show: labels}
|
139
|
+
elsif labels.is_a? Hash
|
140
|
+
LegendOptions.check labels.compact
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def build_markers
|
145
|
+
markers = @options.delete :markers
|
146
|
+
@built[:markers] = if markers.is_a? String
|
147
|
+
{shape: markers}
|
148
|
+
elsif markers.is_a? Hash
|
149
|
+
MarkersOptions.check markers.compact
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def build_no_data
|
154
|
+
no_data = @options.delete :no_data
|
155
|
+
@built[:no_data] = if no_data.is_a? String
|
156
|
+
{text: no_data}
|
157
|
+
elsif no_data.is_a? Hash
|
158
|
+
NoDataOptions.check no_data.compact
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def build_plot_options
|
163
|
+
plot_options = @options.delete :plot_options do
|
164
|
+
@options.delete :plotOptions
|
165
|
+
end
|
166
|
+
@built[:plot_options] = if plot_options.is_a? Hash
|
167
|
+
PlotOptions.check plot_options.compact
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def build_responsive
|
172
|
+
responsive = @options.delete :responsive
|
173
|
+
@built[:responsive] = if responsive.nil?
|
174
|
+
elsif responsive.is_a? Array
|
175
|
+
responsive
|
176
|
+
else
|
177
|
+
[responsive]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def build_states
|
182
|
+
def filter_type_hash(state)
|
183
|
+
if state.is_a? String
|
184
|
+
{filter: {type: state}}
|
185
|
+
elsif state.is_a? Hash
|
186
|
+
state.compact
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
@built[:states] = {
|
191
|
+
normal: filter_type_hash(@options.delete :normal),
|
192
|
+
hover: filter_type_hash(@options.delete :hover),
|
193
|
+
active: filter_type_hash(@options.delete :active)
|
194
|
+
}.compact
|
195
|
+
|
196
|
+
states = @options.delete :states
|
197
|
+
if states.is_a? Hash
|
198
|
+
@built[:states].merge! StatesOptions.check(states.compact)
|
199
|
+
end
|
200
|
+
|
201
|
+
@built[:states] = nil if @built[:states].empty?
|
202
|
+
end
|
203
|
+
|
204
|
+
def build_stroke
|
205
|
+
curve = @options.delete :curve
|
206
|
+
@built[:stroke] = {curve: curve}.compact
|
207
|
+
|
208
|
+
stroke = @options.delete :stroke
|
209
|
+
if [true, false].include? stroke
|
210
|
+
@built[:stroke].merge!({show: stroke})
|
211
|
+
elsif stroke.is_a? Hash
|
212
|
+
@built[:stroke].merge! StrokeOptions.check(stroke.compact)
|
213
|
+
end
|
214
|
+
|
215
|
+
@built[:stroke] = nil if @built[:stroke].empty?
|
216
|
+
end
|
217
|
+
|
218
|
+
def build_subtitle
|
219
|
+
subtitle = @options.delete(:subtitle)
|
220
|
+
@built[:subtitle] = if subtitle.is_a? String
|
221
|
+
{text: subtitle}
|
222
|
+
elsif subtitle.is_a? Hash
|
223
|
+
SubtitleOptions.check subtitle.compact
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def build_theme
|
228
|
+
theme = @options.delete(:theme)
|
229
|
+
@built[:theme] = if theme.is_a?(String)
|
230
|
+
case theme
|
231
|
+
when 'random'
|
232
|
+
{palette: THEME_PALETTES.sample}
|
233
|
+
when 'monochrome'
|
234
|
+
{monochrome: {enabled: true}}
|
235
|
+
else
|
236
|
+
{palette: theme}
|
237
|
+
end
|
238
|
+
elsif theme.is_a?(Hash)
|
239
|
+
ThemeOptions.check theme.compact
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def build_title
|
244
|
+
title = @options.delete(:title)
|
245
|
+
@built[:title] = if title.is_a? String
|
246
|
+
{text: title}
|
247
|
+
elsif title.is_a? Hash
|
248
|
+
TitleOptions.check title.compact
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def build_tooltip
|
253
|
+
tooltip = @options.delete :tooltip
|
254
|
+
@built[:tooltip] = if [true, false].include? tooltip
|
255
|
+
{enabled: tooltip}
|
256
|
+
elsif tooltip.is_a? Hash
|
257
|
+
TooltipOptions.check tooltip.compact
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def build_xaxis
|
262
|
+
xaxis = @options.delete :xaxis
|
263
|
+
@built[:xaxis] = {
|
264
|
+
type: @options.delete(:xtype){ @xtype },
|
265
|
+
title: {
|
266
|
+
text: @options.delete(:xtitle)
|
267
|
+
}.compact
|
268
|
+
}.compact
|
269
|
+
|
270
|
+
if xaxis.is_a? String
|
271
|
+
@built[:xaxis][:title] = {text: xaxis}
|
272
|
+
elsif xaxis.is_a? Hash
|
273
|
+
XAxisOptions.check xaxis
|
274
|
+
@built[:xaxis].merge! xaxis
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def build_yaxis
|
279
|
+
yaxis = @options.delete :yaxis
|
280
|
+
@built[:yaxis] = [{
|
281
|
+
type: @options.delete(:ytype),
|
282
|
+
title: {
|
283
|
+
text: @options.delete(:ytitle)
|
284
|
+
}.compact
|
285
|
+
}.compact]
|
286
|
+
|
287
|
+
if yaxis.is_a? String
|
288
|
+
@built[:yaxis][0][:title] = {text: yaxis}
|
289
|
+
elsif yaxis.is_a? Hash
|
290
|
+
YAxisOptions.check yaxis
|
291
|
+
@built[:yaxis][0].merge! yaxis
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def xtype(x)
|
296
|
+
if DateTime.iso8601(x).iso8601 == x
|
297
|
+
'datetime'
|
298
|
+
elsif Date.iso8601(x).iso8601 = x
|
299
|
+
'datetime'
|
300
|
+
end
|
301
|
+
rescue
|
302
|
+
'number'
|
303
|
+
end
|
304
|
+
|
305
|
+
def enabled(options)
|
306
|
+
boolean_to_hash(options) do |options|
|
307
|
+
{enabled: options}
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def boolean_to_hash(options)
|
312
|
+
return if options.nil?
|
313
|
+
if [true, false].include? options
|
314
|
+
yield(options)
|
315
|
+
elsif options.is_a?(Hash)
|
316
|
+
options.compact
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Apexcharts
|
2
|
+
class CartesianSeries
|
3
|
+
attr_accessor :sanitized
|
4
|
+
|
5
|
+
def initialize(data)
|
6
|
+
if data.is_a?(Array)
|
7
|
+
if (data.to_h rescue nil)
|
8
|
+
@sanitized = [data.to_h]
|
9
|
+
else
|
10
|
+
@sanitized = data.map(&:to_h)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
@sanitized = [data]
|
14
|
+
end
|
15
|
+
|
16
|
+
unless sanitized[0][:data]
|
17
|
+
@sanitized = sanitized.map{|a| {data: a} }
|
18
|
+
end
|
19
|
+
|
20
|
+
@sanitized = sanitized.each {|a| a[:data] = a[:data].map{|k,v| {x: k, y: v} } }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'series/cartesian'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Apexcharts::Utils
|
4
|
+
class DateTime
|
5
|
+
def self.convert input
|
6
|
+
case input
|
7
|
+
when Time
|
8
|
+
(input.to_f * 1000).round
|
9
|
+
when ::DateTime, Date
|
10
|
+
(input.to_time.to_f * 1000).round
|
11
|
+
else
|
12
|
+
if (dt = ::DateTime.iso8601(input)).iso8601 == input
|
13
|
+
(dt.to_time.to_f * 1000).round
|
14
|
+
else (d = Date.iso8601(input)).iso8601 == input
|
15
|
+
(d.to_time.to_f * 1000).round
|
16
|
+
end
|
17
|
+
end
|
18
|
+
rescue
|
19
|
+
input
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.convert_range input
|
23
|
+
case input.first
|
24
|
+
when Time
|
25
|
+
((input.first.to_f * 1000).round..(input.last.to_f * 1000).round)
|
26
|
+
when ::DateTime, Date
|
27
|
+
((input.first.to_time.to_f * 1000).round..(input.last.to_time.to_f * 1000).round)
|
28
|
+
else
|
29
|
+
if (dt = ::DateTime.iso8601(input.first)).iso8601 == input.first
|
30
|
+
((dt.to_time.to_f * 1000).round..(::DateTime.iso8601(input.last).to_time.to_f * 1000).round)
|
31
|
+
else (d = Date.iso8601(input.first)).iso8601 == input.first
|
32
|
+
((d.to_time.to_f * 1000).round..(Date.iso8601(input.last).to_time.to_f * 1000).round)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
rescue
|
36
|
+
input
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.xtype input
|
40
|
+
case input
|
41
|
+
when Time
|
42
|
+
'datetime'
|
43
|
+
when DateTime, Date
|
44
|
+
'datetime'
|
45
|
+
when Date
|
46
|
+
'date'
|
47
|
+
else
|
48
|
+
if DateTime.iso8601(input).iso8601 == input
|
49
|
+
'datetime'
|
50
|
+
elsif Date.iso8601(input).iso8601 == input
|
51
|
+
'datetime'
|
52
|
+
else
|
53
|
+
'number'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
rescue
|
57
|
+
'number'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Apexcharts
|
2
|
+
module Utils
|
3
|
+
module Hash
|
4
|
+
def deep_merge(first_hash, second_hash)
|
5
|
+
first_hash.merge(second_hash) do |key, this_val, other_val|
|
6
|
+
if this_val.is_a?(::Hash) && other_val.is_a?(::Hash)
|
7
|
+
deep_merge(this_val.dup, other_val)
|
8
|
+
else
|
9
|
+
other_val
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
module_function :deep_merge
|
14
|
+
|
15
|
+
def camelize(key)
|
16
|
+
key.to_s.gsub(/_(.)/) {|m| m[1].upcase }.to_sym
|
17
|
+
end
|
18
|
+
module_function :camelize
|
19
|
+
|
20
|
+
def camelize_keys(value)
|
21
|
+
if value.is_a? ::Hash
|
22
|
+
::Hash[value.map {|k, v| [camelize(k), camelize_keys(v)] }]
|
23
|
+
else
|
24
|
+
value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
module_function :camelize_keys
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/lib/apexcharts.rb
ADDED