google_image_chart 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +16 -0
- data/README.md +36 -0
- data/examples/example.rb +10 -0
- data/examples/google_image_chart.rb +32 -0
- data/lib/google_image_chart.rb +109 -0
- data/spec/fixtures/cassette_library/google_charts.json +1 -0
- data/spec/google_image_chart_spec.rb +95 -0
- data/spec/spec_helper.rb +31 -0
- metadata +78 -0
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem 'awesome_print', '~> 1.0.2'
|
7
|
+
gem 'pry', '~> 0.9.10'
|
8
|
+
gem 'rake', '~> 0.9.2.2'
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'multi_json', '~> 1.3.6'
|
13
|
+
gem 'rspec', '~> 2.9.0'
|
14
|
+
gem 'vcr', '~> 2.2.5'
|
15
|
+
gem 'webmock', '~> 1.8.10'
|
16
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# GoogleImageChart
|
2
|
+
|
3
|
+
Simple wrapper to Google Image Chart. As the service will be switched
|
4
|
+
off in on or before 20 April 2015, this has been mostly put together for
|
5
|
+
legacy reasons. It's easier to drop a gem from a service rather than
|
6
|
+
delete code (and specs)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'google_image_chart'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install google_image_chart
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Check the examples directory. To run a specific example:
|
25
|
+
|
26
|
+
$ ruby examples/google_image_chart.rb
|
27
|
+
|
28
|
+
NB: you will need to have all gems in the `development` group installed.
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
|
32
|
+
1. Fork it
|
33
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
34
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
35
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
36
|
+
5. Create new Pull Request
|
data/examples/example.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative 'example'
|
4
|
+
require_relative '../lib/google_image_chart'
|
5
|
+
|
6
|
+
line_chart_png = GoogleImageChart.new(
|
7
|
+
type: "lc:nda",
|
8
|
+
axes: %w[x y],
|
9
|
+
axes_range: %w[1 0 100 10],
|
10
|
+
margins: [%w[10 10 10 10]],
|
11
|
+
colours: %w[000000 FF0000],
|
12
|
+
line_styles: %w[5 2,5],
|
13
|
+
labels: [
|
14
|
+
%w[8:00 8:05 8:10 8:15 8:20 8:25 8:30 8:35 8:40 8:45 8:50 8:55 9:00]
|
15
|
+
],
|
16
|
+
data: [
|
17
|
+
%w[30 20 40 10 30 20 40 50 60 70 90 50 90],
|
18
|
+
%w[70 70 70 70 70 70 70 70 70 70 70 70]
|
19
|
+
],
|
20
|
+
markers: [
|
21
|
+
"N,FF0000,0,9,15",
|
22
|
+
"N,FF0000,0,10,15",
|
23
|
+
"N,FF0000,0,12,15",
|
24
|
+
"v,DDDDDD,0,::1,1,-1"
|
25
|
+
]
|
26
|
+
)
|
27
|
+
|
28
|
+
exemplify("Google Image Chart API url", line_chart.url)
|
29
|
+
|
30
|
+
puts "\nOpening generated PNG...\n"
|
31
|
+
|
32
|
+
`open "#{line_chart_png.url}"`
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
require 'hashie/dash'
|
6
|
+
|
7
|
+
class GoogleImageChart < Hashie::Dash
|
8
|
+
property :type, default: "lc"; alias :cht :type
|
9
|
+
property :width, default: 600
|
10
|
+
property :height, default: 200
|
11
|
+
property :margins, default: [%w[0 0 0 0]]
|
12
|
+
property :colours
|
13
|
+
property :axes, default: %w[x]
|
14
|
+
property :axes_range
|
15
|
+
property :line_styles
|
16
|
+
property :labels
|
17
|
+
property :label_styles
|
18
|
+
property :legend_labels
|
19
|
+
property :legend_position, default: "b"; alias :chdlp :legend_position
|
20
|
+
property :data
|
21
|
+
property :markers
|
22
|
+
|
23
|
+
def url
|
24
|
+
URI.escape("#{baseurl}#{properties}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def image_data
|
28
|
+
Net::HTTP.get(
|
29
|
+
URI.parse(url)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def base64
|
34
|
+
Base64.encode64(image_data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def properties
|
38
|
+
%w[
|
39
|
+
cht chs chma chco chxt chxr chls chxl chxs chdl chdlp chd chm
|
40
|
+
].inject([]) { |result, property|
|
41
|
+
if value = self.send(property)
|
42
|
+
result << "#{property}=#{value}"
|
43
|
+
end
|
44
|
+
result
|
45
|
+
}.join("&")
|
46
|
+
end
|
47
|
+
|
48
|
+
def chs
|
49
|
+
"#{width}x#{height}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def chxt
|
53
|
+
axes && axes.join(',')
|
54
|
+
end
|
55
|
+
|
56
|
+
def chxr
|
57
|
+
axes_range && axes_range.join(',')
|
58
|
+
end
|
59
|
+
|
60
|
+
def chd
|
61
|
+
result = ''
|
62
|
+
|
63
|
+
first_data_group = data.slice(0,1).flatten
|
64
|
+
result << 't:' << first_data_group.join(',')
|
65
|
+
|
66
|
+
all_other_data_groups = data.slice(1,data.size)
|
67
|
+
all_other_data_groups && all_other_data_groups.map { |values| result << '|' << values.join(',') }
|
68
|
+
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
def chls
|
73
|
+
line_styles && line_styles.join('|')
|
74
|
+
end
|
75
|
+
|
76
|
+
def chma
|
77
|
+
margins && margins.map { |group| group.join(',') }.join('|')
|
78
|
+
end
|
79
|
+
|
80
|
+
def chco
|
81
|
+
colours && colours.join(',')
|
82
|
+
end
|
83
|
+
|
84
|
+
def chm
|
85
|
+
markers && markers.join('|')
|
86
|
+
end
|
87
|
+
|
88
|
+
def chxl
|
89
|
+
labels && labels.each_with_index.inject([]) { |result, (labels, index)|
|
90
|
+
result << "#{index}:|#{labels.join('|')}"
|
91
|
+
}.join(',')
|
92
|
+
end
|
93
|
+
|
94
|
+
def chdl
|
95
|
+
legend_labels && legend_labels.join('|')
|
96
|
+
end
|
97
|
+
|
98
|
+
def chxs
|
99
|
+
label_styles && label_styles.join(',')
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def baseurl
|
107
|
+
"http://chart.apis.google.com/chart?"
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"http_interactions":[{"request":{"method":"get","uri":"http://chart.apis.google.com/chart?chco=000000,FF0000&chd=t:30,20,40,10,30,20,40,50,60,70,90,50,90%7C70,70,70,70,70,70,70,70,70,70,70,70&chdlp=b&chls=5%7C2,5&chm=N,FF0000,0,9,15%7CN,FF0000,0,10,15%7CN,FF0000,0,12,15%7Cv,DDDDDD,0,::1,1,-1&chma=10,10,10,10&chs=600x200&cht=lc:nda&chxl=0:%7C8:00%7C8:05%7C8:10%7C8:15%7C8:20%7C8:25%7C8:30%7C8:35%7C8:40%7C8:45%7C8:50%7C8:55%7C9:00&chxr=1,0,100,10&chxt=x,y","body":{"encoding":"US-ASCII","base64_string":""},"headers":{"Accept":["*/*"],"User-Agent":["Ruby"]}},"response":{"status":{"code":200,"message":"OK"},"headers":{"Date":["Fri, 14 Sep 2012 22:31:11 GMT"],"Expires":["Sat, 15 Sep 2012 22:31:11 GMT"],"Cache-Control":["public, max-age=86400"],"Last-Modified":["Mon, 20-Aug-2012 09:57:21 GMT"],"X-Frame-Options":["ALLOWALL"],"Access-Control-Allow-Origin":["*"],"Content-Type":["image/png"],"X-Content-Type-Options":["nosniff"],"Server":["GoogleChartAPI/1.0"],"Content-Length":["14744"],"X-Xss-Protection":["1; mode=block"]},"body":{"encoding":"ASCII-8BIT","base64_string":"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\nWYiPSVIHKzd46tQpoZcb5AgSIQBgOHj37l1ERAQ3twClpKQcHBxG5i1A7nl5\ned28efPy5cu0lvv37//2229ffvmlsHZx+vRphnKDq1evXrt2rbC2zz24NAoA\nGMK6u7uvXLnC5S1AY2Njb29vDw8PhllU+DOML41impubCQRCQ0MDrUVZWfnF\nixdmZmaCb5y53KCurm5hYaGWlpbgG6cHl0YBAMMTlUp98OBBVFTUzZs3Ga6t\nMePvFiAYM2ZMRESEm5sb7Xypu7vbz88vMzOTYSI0Xg0MDHz++ecM5QYjIiKE\nngW5xC4R9vf33759u6qqyt7e3s7ODiEEhXkBAPgqKSkJDw+PjY19+/Yt+zXl\n5eWXLl3q4+Mzf/58BQUF8YQ3zCxYsGDDhg3nz5+nteTk5ISEhPzwww+CbDY4\nODgnJ4e+5Ysvvpg/f74g2xQIm3lIDx48mJOTU15evmPHjvLyciqVGhQUlJiY\n+OLFi++++66rq0uQiVABAIB7HR0d4eHhTk5O3JzSEQiEw4cPY/XjREfAea6F\nS3TBtLe3T5gwgb57FRQUCgsL+d5gYWEhw98lEydObG9vF2LM9LiZdJvlGWFn\nZ6eamhp2Ivjjjz/KyclVVFT09/e7u7sjhIqKikpKSv5VmBcAAISNj1uAnp6e\n5ubm4glvJFBXV4+Li5szZw6t/3t7e9esWfP8+XM+HrXt6elZs2ZNb28vrUVG\nRiY2NvafIlY4Yfm3VXl5uZaWVlJS0pkzZ9ra2tTV1VtaWnR1/6kYrKurW1xc\njBCqra198uTJkydPOE5WBAAAXKJSqffv3/f19dXX1/fz87t//z6bLDhmzBh/\nf/9nz56VlpYGBgZCFhQ6R0fHnTt30rf8/fff+/fv52NT+/btY3isd9euXY6O\njgLFJzCWZ4QNDQ25ubmrV692cHD4+eef/fz8Bi3Mq6GhgVXuUFFREU/EAIBh\nDG4BSqb//ve/9+7dKywspLX88ssvixYtmjNnDvcbefjwYWhoKH2LpaXlgQMH\nhBYlv1gmwvHjx1tZWWElMObOnVtUVGRqakorYdze3q6jo4MQGjVqFC07AgAA\nfxobG+Pi4qKjo58/f85+TdoowFWrVnF8LB4Ii4KCQlRUlJ2dXV9fH9ZCoVDW\nrVuXn5+vqqrKzRbev3+/bt06+kJX8vLykZGRkvBHDMtLo0ZGRq9evcKCbmxs\n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\nPJCWlnZ0dCQQCGjkFea9c+fO559/zvywu6amZlhYmIAPu//nP/9pa2s7duwY\nraW/v3/lypXJycnMA/DBUCHSYwYAIAoszwjb2tpiY2OdnZ3nzp177ty51tZW\nhFBoaKiCggKBQDhy5AiRSGR4C3PL0EUmk/ft27dkyRLmb7Tp06c/efJEKN9o\nR44cWbFiBX0LiURavnx5cXGx4BuXcD09PZmZmbW1tXgHIjTiOWYAAELHMhE2\nNDTMnz/fwsLC3NzcwMCgubmZVpjX2traxsampKSEfn0KhTJ16tS5c+eGh4d3\ndnaKPnIRqq6udnJyOnDgAEN9VCkpqd27d2dlZRkbGwtlRzIyMhcvXnR2dqZv\nxCYjrampEcouJBCVSg0NDdXW1v7kk08mTpwIxwwAAGfsZ2ArKioKDw8/duxY\nX1/f06dPT58+jbWnp6fHxcVRqdT+/n4SiUQike7du0fbpoyMjIuLS2RkJJFI\nFGyWOBxERUUNWvXb0NAwOzubjw1ynHaPSCQ6Ojoy7G64TkZaU1MzaN0SOGbo\nSdRUjRAMKxAMKxIVjBDmGpWVlR01apSCggKFQhm0MG91dXVGRkZGRkZSUhLt\nXQMDA/fv3/fz8zMyMtq5cyf7otuSg0Qibd682dfXl3nI18KFC7Ozs0U05EtZ\nWTkhIcHU1JS+sbS0dNmyZcPpajNCKDk5edq0aenp6cyL4JgBAOCGVYasr6/v\n6OjAfo6Pj79582Z+fn5ISAjWkpaWlpiYSL9+QEAAm71MmDAhICCgpKREgLwu\nWo8ePWKYCxSDDfkSZMtc/nFUU1PDHICTkxOJRBJk7xKCSCT6+PjwdGTCMSMh\nIBhWIBhWJCoYgc4I//7777t37yKE+vv7W1tb1dTUzM3NOzs7sRPB/Pz88ePH\n06/Pfo6ot2/fhoSEWFhYzJs3LzIykvnPZ3z99ttvzs7OzEO+TE1NHz58KJ4h\nX/r6+jdv3hw9ejR9Y3p6+oYNGygUihgCEJ2ysjInJ6fo6Gie3gXHDABATFhl\nyP7+/kOHDp08efL7778/evRoT08PlUpNS0vbt29faGhoREQEc9Z9+fJlQEAA\nw7zSg1JQUFi8ePHly5d7e3sFzPYCqqurc3FxGTRIrDKc4Lvg6Y+jJ0+eqKio\nMETi5+c3dAtAHj9+XElJibl79fT0oqOj4ZgZlET9QQ3BsALBsCJRwXBzRsjh\n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\n6Y0fPz44OJi5sh0AAAAw5PBwRvjy5UttbW0nJyeEUF5eXmVlpaGhoajiAgAA\nAMSChzPC5uZm2uRqenp6UJgXAADAMMDDGWFvby99YV6sAGFJSUlJSQlCyNzc\nfPTo0aIIkQ+SEwmCYFiDYFiBYFiBYFiBYFhRVFTkuA4PiVBVVRXLeQihtrY2\nhsK8EkWi/hsgGFYgGFYgGFYgGFYgGFaUlJQ4rsPDpVFLS8va2tq+vj6EUEFB\nARTmBQAAMAxI8fTw561bt/Ly8mRlZT/66KOlS5eKLiwAAABAPHhLhAghIpFI\nJBLHjh0rooAAAAAAceJtQH1ZWdnDhw8VFRWdnZ0ZitT39PSkpKQ0Nze7ublh\ni8hkclpaWkVFxfz58w0MDIQYNB/BpKSkPHv2DFvq6Og4e/ZssQWDCQsL27Bh\nA/Yzjj3DHAyOPdPQ0JCUlNTX1zd79uzJkycjXHuGORgce6a2tjY5Obmrq8va\n2vqTTz5BuPYMczC4/zZVVlbm5OR4eHggCfhtog8Gx55JSEigPcnv5uZmbW2N\nY88wByPqnikpKXn06JGampqrq6uqqir9Im5yEw/3CAcGBuLj4y0tLe3s7H7+\n+WfsqVGaEydO9Pf3T58+/eTJky0tLQih8PDwuro6JyeniIiIsrIywT+qIMGU\nlpYuXLhw/fr169evt7W1FWcwpaWlUVFRz58/p7Xg2DPMweDYM6dOnTI0NFy+\nfPnt27dv3LiBcO0Z5mDw6hkqlXru3DkCgbB69epr1669evUK4dczgwaD4zGD\nEOrt7Q0PD3/37h32EsdjhjkYHHumqKho1apV2K7Nzc0Rrj3DHIxIe6anp+fP\nP/+0tbW1srIKCgrq7++nX8pNbuLhjLCsrIxMJtva2kpJSZmamjY1NY0ePfrG\njRu6urqTJk1qamoKCAhACNnZ2RUVFdna2hYUFBw7dkxOTs7Z2fn169fGxsZC\n/OQ8BePo6NjU1GRmZiYrK6ugoCDEMDgGM2PGjO7u7vHjx0tL//M3R09PD149\nwxwMQgivnjEwMNDT08PmZ3B1dX348CGOPcMcDMKvZwwNDadNmzZt2jSE0LRp\n05qamnDsGeZgEH49M2PGDIRQbGzsxx9/XFVVhfD+bWIIBuHaMx0dHcbGxn19\nfdiu8e0ZhmCQiHsmJyfHzs6OQCAghKytrSsrK01NTXnKTTwkQjMzMz09vfPn\nz5NIJDKZjI2asLCwUFVVZRhrX1hYaGhoqKGhIScnh7XQToqFhadgHB0dW1pa\nfv31V6zF3d1dU1NTPMEghCwtLRFC165dw1ZubW3Fq2eYg0EI4dUzY8eO/fLL\nLxFCFArl6dOnkydPxrFnmINB+PWMtrb2kiVL6urq0tLSampq3NzccOwZ5mAQ\nfj2DEHry5ImSkhKBQMByD76/TQzBIPx6hkgkkkik4OBgGRkZAwMDNze39+/f\n49UzzMGoqqqKtGcUFRUfP348f/58KpXa1dVVVlZmamrKU27i4dJoW1tbTU2N\niorK1KlTOzs7sb8Nzc3N9fT0GMbak0gkhpbu7m4hfmxegyGTycuWLduxY0dA\nQACVSr1165bYgmFeGceeYV4Z956pqqo6fPiwpqami4sL7j1DHwzuPSMtLa2i\noiIvL48k4JihDwbHnmlpaUlPT1+xYgVtZRx7hjkYfI+Z1atX7969+7vvvquv\nr09NTcX3mGEIRtQ9Y21traGh8ccff4SGhnZ1dWFPgPKUm3hIhNnZ2ba2tp6e\nns7OzgQCISsri7ZIVVW1oaEB+7mtrW3s2LGqqqq06+a00fdCxFMwsrKyc+fO\nxU7JXV1dq6urxRYMMxx7hhm+PfPo0aOoqCgvL6/ly5dLSUnh2zMMweDYM62t\nrc3NzePGjVu6dKmdnd3ly5dx7BnmYHDsmUePHnV3d//222/x8fHV1dVhYWE4\n9gxzMDj2zKhRo2bNmiUrK4vt+u3btzj2DHMwou4ZRUXFzZs3L1269OuvvzY1\nNaW/CMxlbuIhEWppaWEzy1Cp1L6+Puxhm87OThKJZGRkRCaTOzs70f/H2o8Z\nM0ZbW7u2thYhlJ+fL/TR9zwF09zcHBwcTKFQEELFxcXYxX3xBMO8Mo49w7wy\njj3T19f34MGDXbt2TZgwAVsZx55hDgbHnmlsbLx48SK2qLGxUU1NDceeYQ4G\nx55xcXHx9/f38fFZsGCBrq7uihUrcOwZ5mBw7JnS0lLswiOVSn3z5s2MGTNw\n7BnmYETdM+Xl5efPn9fU1JSTk8vNzZ00aRLiMTfJBAYGcrkzbW3t6urqjIyM\nO3fuUCiUZcuWIYQuXLjQ2dlpamqqrKwcERFRWFgoIyOzdOlSKSkpLS2tCxcu\nvH79urm52cvLi/4BDcHxFMyoUaMaGxsTExMzMzPLy8s9PDywizxiCMbExARb\nJykpadGiRdjPePUMczDKysp49Uxvb+/Dhw/T0tLu3r179+7dioqK6dOn49Uz\nzMHMmTMHr56xt7cvLCxMTU1NS0urq6vz8vJSUlLCq2eYg9HS0sKrZywsLJSU\nlJSUlLq7u8vKyrCHm/DqGeZgcPxtmj59enFxcUpKSmpqakdHx4oVK6SlpfHq\nGeZgVFRURNozqqqqDx8+zM7OzszMnDdvHlYWiafcxPOAeuwaq4aGBvOi/v7+\npqYmXV1dKSkprIVCodTX148bN05GRkbwTytgMGQyua2tTVtbWxSRsA+GGY49\nwwx6hhUce6arq4tEItHvGseeYQ4GjhlWcOyZ3t5eIpFI/xwKjj3DHIxIe4ZK\npdbX16uqqjIMIsRwzE08J0IAAABgOBHmyTIAAAAw5EAiBAAAMKJBIgQAADCi\nQSIEAAAwov0PLg9T4bubCpoAAAAASUVORK5CYII=\n"},"http_version":null},"recorded_at":"Fri, 14 Sep 2012 22:31:11 GMT"}],"recorded_with":"VCR 2.2.5"}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'google_image_chart'
|
3
|
+
|
4
|
+
describe GoogleImageChart do
|
5
|
+
describe "by default" do
|
6
|
+
subject { GoogleImageChart.new }
|
7
|
+
|
8
|
+
its(:type) { should eql "lc" }
|
9
|
+
its(:cht) { should eql "lc" }
|
10
|
+
|
11
|
+
its(:width) { should eql 600 }
|
12
|
+
its(:height) { should eql 200 }
|
13
|
+
its(:chs) { should eql "600x200" }
|
14
|
+
|
15
|
+
its(:margins) { should eql [%w[0 0 0 0]] }
|
16
|
+
its(:chma) { should eql "0,0,0,0" }
|
17
|
+
|
18
|
+
its(:axes) { should eql %w[x] }
|
19
|
+
|
20
|
+
its(:legend_position) { should eql "b" }
|
21
|
+
its(:chdlp) { should eql "b" }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "line chart" do
|
25
|
+
subject do
|
26
|
+
GoogleImageChart.new(
|
27
|
+
type: "lc:nda",
|
28
|
+
axes: %w[x y],
|
29
|
+
axes_range: %w[1 0 100 10],
|
30
|
+
margins: [%w[10 10 10 10]],
|
31
|
+
colours: %w[000000 FF0000],
|
32
|
+
line_styles: %w[5 2,5],
|
33
|
+
labels: [
|
34
|
+
%w[8:00 8:05 8:10 8:15 8:20 8:25 8:30 8:35 8:40 8:45 8:50 8:55 9:00]
|
35
|
+
],
|
36
|
+
data: [
|
37
|
+
%w[30 20 40 10 30 20 40 50 60 70 90 50 90],
|
38
|
+
%w[70 70 70 70 70 70 70 70 70 70 70 70]
|
39
|
+
],
|
40
|
+
markers: [
|
41
|
+
"N,FF0000,0,9,15",
|
42
|
+
"N,FF0000,0,10,15",
|
43
|
+
"N,FF0000,0,12,15",
|
44
|
+
"v,DDDDDD,0,::1,1,-1"
|
45
|
+
]
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
its(:chd) { should eql "t:30,20,40,10,30,20,40,50,60,70,90,50,90|70,70,70,70,70,70,70,70,70,70,70,70" }
|
50
|
+
its(:chxl) { should eql "0:|8:00|8:05|8:10|8:15|8:20|8:25|8:30|8:35|8:40|8:45|8:50|8:55|9:00" }
|
51
|
+
its(:chxr) { should eql "1,0,100,10" }
|
52
|
+
|
53
|
+
describe "#image_data" do
|
54
|
+
it "returns the image content" do
|
55
|
+
VCR.use_cassette('google_charts') do
|
56
|
+
subject.image_data.should include("PNG")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#url" do
|
62
|
+
it "valid url with all parameters" do
|
63
|
+
subject.url.should eql("http://chart.apis.google.com/chart?cht=lc:nda&chs=600x200&chma=10,10,10,10&chco=000000,FF0000&chxt=x,y&chxr=1,0,100,10&chls=5%7C2,5&chxl=0:%7C8:00%7C8:05%7C8:10%7C8:15%7C8:20%7C8:25%7C8:30%7C8:35%7C8:40%7C8:45%7C8:50%7C8:55%7C9:00&chdlp=b&chd=t:30,20,40,10,30,20,40,50,60,70,90,50,90%7C70,70,70,70,70,70,70,70,70,70,70,70&chm=N,FF0000,0,9,15%7CN,FF0000,0,10,15%7CN,FF0000,0,12,15%7Cv,DDDDDD,0,::1,1,-1")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "pie chart" do
|
69
|
+
subject do
|
70
|
+
GoogleImageChart.new(
|
71
|
+
type: "p",
|
72
|
+
width: 240,
|
73
|
+
height: 157,
|
74
|
+
margins: [
|
75
|
+
%w[0 0 0 0],
|
76
|
+
%w[0 30]
|
77
|
+
],
|
78
|
+
colours: %w[308DF3 00FF00 FF0000],
|
79
|
+
legend_labels: %w[Group\ A Group\ B Group\ C],
|
80
|
+
label_styles: %w[0 67676700 11.167],
|
81
|
+
data: [%w[20 10 5]]
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
its(:chma) { should eql "0,0,0,0|0,30" }
|
86
|
+
its(:chxs) { should eql "0,67676700,11.167" }
|
87
|
+
its(:chdl) { should eql "Group A|Group B|Group C" }
|
88
|
+
|
89
|
+
describe "#url" do
|
90
|
+
it "valid url with all parameters" do
|
91
|
+
subject.url.should eql("http://chart.apis.google.com/chart?cht=p&chs=240x157&chma=0,0,0,0%7C0,30&chco=308DF3,00FF00,FF0000&chxt=x&chxs=0,67676700,11.167&chdl=Group%20A%7CGroup%20B%7CGroup%20C&chdlp=b&chd=t:20,10,5")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
APP_ROOT = File.expand_path('../../', __FILE__)
|
6
|
+
lib = "#{APP_ROOT}/lib"
|
7
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
8
|
+
|
9
|
+
require 'vcr'
|
10
|
+
|
11
|
+
VCR.configure do |c|
|
12
|
+
c.cassette_library_dir = "#{APP_ROOT}/spec/fixtures/cassette_library"
|
13
|
+
c.hook_into :webmock
|
14
|
+
c.ignore_localhost = true
|
15
|
+
c.default_cassette_options = {
|
16
|
+
:record => :new_episodes,
|
17
|
+
:serialize_with => :json,
|
18
|
+
:preserve_exact_body_bytes => true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rspec'
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
config.mock_with :rspec
|
26
|
+
|
27
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
28
|
+
config.filter_run :focus => true
|
29
|
+
config.run_all_when_everything_filtered = true
|
30
|
+
config.extend VCR::RSpec::Macros
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google_image_chart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Gerhard Lazu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hashie
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.0
|
30
|
+
description: Creates PNGs from chart data
|
31
|
+
email:
|
32
|
+
- gerhard@lazu.co.uk
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/google_image_chart.rb
|
38
|
+
- examples/example.rb
|
39
|
+
- examples/google_image_chart.rb
|
40
|
+
- Gemfile
|
41
|
+
- README.md
|
42
|
+
- spec/fixtures/cassette_library/google_charts.json
|
43
|
+
- spec/google_image_chart_spec.rb
|
44
|
+
- spec/spec_helper.rb
|
45
|
+
homepage: https://github.com/gosquared/google_image_chart
|
46
|
+
licenses: []
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
hash: -1656476349801950249
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
hash: -1656476349801950249
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.23
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Simple wrapper to the Google Image Chart API - yes, the deprecated one
|
75
|
+
test_files:
|
76
|
+
- spec/fixtures/cassette_library/google_charts.json
|
77
|
+
- spec/google_image_chart_spec.rb
|
78
|
+
- spec/spec_helper.rb
|