db_graph 0.1.6
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.
- data/.gitignore +1 -0
- data/README.markdown +46 -0
- data/Rakefile +22 -0
- data/VERSION +1 -0
- data/db_graph.gemspec +59 -0
- data/exmaples/multi_line_graph.rb +17 -0
- data/lib/db_graph/line.rb +128 -0
- data/spec/db_graph/line_spec.rb +239 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/test_model.rb +16 -0
- metadata +95 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/README.markdown
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
Gem/Rails plugin to generate graphs from all your date fields, beautifully simple and combineable.
|
2
|
+
|
3
|
+
Examples
|
4
|
+
========
|
5
|
+
Weeks and months
|
6
|
+

|
7
|
+

|
8
|
+
|
9
|
+
Install
|
10
|
+
=======
|
11
|
+
As Gem:
|
12
|
+
sudo gem install db_graph
|
13
|
+
|
14
|
+
Or as Rails plugin:
|
15
|
+
sudo gem install gchartrb
|
16
|
+
./script/plugins install git://github.com/grosser/db_graph.git
|
17
|
+
|
18
|
+
|
19
|
+
Usage
|
20
|
+
=====
|
21
|
+
DBGraph::Line.url(:weeks, User, :created_at, :at=>Time.now)
|
22
|
+
|
23
|
+
Or instance interface for multiple lines
|
24
|
+
#everything
|
25
|
+
g = DBGraph::Line.new(:weeks)
|
26
|
+
|
27
|
+
#selected interval (:at is expanded to a interval, here: 2009-2010)
|
28
|
+
g = DBGraph::Line.new(:weeks, :at=>Time.parse('2009-01-02'), :show_legend=>false)
|
29
|
+
|
30
|
+
g.add(User, :created_at)
|
31
|
+
g.add(Item, :sold_at, :label=>'Things we sold')
|
32
|
+
g.add(Product, :sold_at, :conditions=>['merchandise = ?',false])
|
33
|
+
...
|
34
|
+
g.to_url --> google chart url with all your data as line graph
|
35
|
+
|
36
|
+
We got :minutes, :hours, :days, :weeks, :months and seconds/years can be added if someone needs them...
|
37
|
+
|
38
|
+
TODO
|
39
|
+
====
|
40
|
+
- weeks/months from beginning of data (->all years)
|
41
|
+
|
42
|
+
Author
|
43
|
+
======
|
44
|
+
[Michael Grosser](http://pragmatig.wordpress.com)
|
45
|
+
grosser.michael@gmail.com
|
46
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
project_name = 'db_graph'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = project_name
|
10
|
+
gem.summary = "AR generate beautiful graphs from date fields, in 1 LOC"
|
11
|
+
gem.email = "grosser.michael@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/grosser/#{project_name}"
|
13
|
+
gem.authors = ["Michael Grosser"]
|
14
|
+
gem.add_dependency ['gchartrb']
|
15
|
+
gem.add_dependency ['activesupport']
|
16
|
+
gem.add_dependency ['activerecord']
|
17
|
+
end
|
18
|
+
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
22
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.6
|
data/db_graph.gemspec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{db_graph}
|
8
|
+
s.version = "0.1.6"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2009-12-13}
|
13
|
+
s.email = %q{grosser.michael@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.markdown"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".gitignore",
|
19
|
+
"README.markdown",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"db_graph.gemspec",
|
23
|
+
"exmaples/multi_line_graph.rb",
|
24
|
+
"lib/db_graph/line.rb",
|
25
|
+
"spec/db_graph/line_spec.rb",
|
26
|
+
"spec/spec_helper.rb",
|
27
|
+
"spec/test_model.rb"
|
28
|
+
]
|
29
|
+
s.homepage = %q{http://github.com/grosser/db_graph}
|
30
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
s.rubygems_version = %q{1.3.5}
|
33
|
+
s.summary = %q{AR generate beautiful graphs from date fields, in 1 LOC}
|
34
|
+
s.test_files = [
|
35
|
+
"spec/spec_helper.rb",
|
36
|
+
"spec/db_graph/line_spec.rb",
|
37
|
+
"spec/test_model.rb"
|
38
|
+
]
|
39
|
+
|
40
|
+
if s.respond_to? :specification_version then
|
41
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
42
|
+
s.specification_version = 3
|
43
|
+
|
44
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
45
|
+
s.add_runtime_dependency(%q<gchartrb>, [">= 0"])
|
46
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
47
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<gchartrb>, [">= 0"])
|
50
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
51
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<gchartrb>, [">= 0"])
|
55
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
56
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'active_support'
|
4
|
+
require 'spec/test_model'
|
5
|
+
|
6
|
+
$LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
|
7
|
+
require 'db_graph/line'
|
8
|
+
|
9
|
+
1000.times{Product.create!(:created_at=>Time.parse('2008-01-01')+rand(1.year), :updated_at=>Time.parse('2008-01-01')+rand(1.year))}
|
10
|
+
500.times{Product.create!(:created_at=>Time.parse('2008-10-01')+rand(2.months), :updated_at=>Time.parse('2008-10-01')+rand(2.months))}
|
11
|
+
|
12
|
+
[:weeks, :months].each do |interval|
|
13
|
+
g = DBGraph::Line.new(interval, :size=>'445x400', :show_legend=>(interval!=:weeks))
|
14
|
+
g.add Product, :created_at
|
15
|
+
g.add Product, :updated_at
|
16
|
+
puts ""
|
17
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
gem 'gchartrb'
|
2
|
+
require 'google_chart'
|
3
|
+
|
4
|
+
module DBGraph
|
5
|
+
class Line
|
6
|
+
NUM_Y_LABELS = 10
|
7
|
+
|
8
|
+
attr_accessor :data
|
9
|
+
|
10
|
+
def initialize(style, options={})
|
11
|
+
@style = style.to_sym
|
12
|
+
@options = options
|
13
|
+
self.data = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(model, attribute, options={})
|
17
|
+
label = options.delete(:label) || "#{model} #{attribute}"
|
18
|
+
data[label] = count(model, attribute, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def count(model, attribute, options={})
|
22
|
+
scope = if @options[:at]
|
23
|
+
start, ende = interval_for(@options[:at])
|
24
|
+
model.scoped(:conditions=>["#{attribute} BETWEEN ? AND ?", start, ende]).scoped(options)
|
25
|
+
else
|
26
|
+
model.scoped(options)
|
27
|
+
end
|
28
|
+
data_type = @style.to_s.sub(/s$/,'').upcase
|
29
|
+
scope.count(:group=>"#{data_type}(#{attribute})")
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_url
|
33
|
+
size = @options[:size] || '600x500'
|
34
|
+
GoogleChart::LineChart.new(size, nil, false) do |line|
|
35
|
+
for name, hash in data
|
36
|
+
line.data(name, klass.filled_and_sorted_values(hash, x_values), klass.color_for(name))
|
37
|
+
end
|
38
|
+
line.axis :x, :labels => x_labels
|
39
|
+
line.axis :y, :labels => y_labels
|
40
|
+
line.show_legend = (@options[:show_legend]!=false)
|
41
|
+
end.to_url
|
42
|
+
end
|
43
|
+
|
44
|
+
def x_labels
|
45
|
+
case @style
|
46
|
+
when :days then x_values.map{|x|x%5==0 ? x : ''}
|
47
|
+
when :weeks, :minutes then x_values.map{|x|x%10==0 ? x : ''}
|
48
|
+
else x_values
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def y_labels
|
53
|
+
values = []
|
54
|
+
data.each{|name,hash|values += klass.filled_and_sorted_values(hash, x_values)}
|
55
|
+
distribute_evently(values, NUM_Y_LABELS)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.url(style, model, attribute, options={})
|
59
|
+
g = self.new(style, :at=>options.delete(:at))
|
60
|
+
g.add model, attribute, options
|
61
|
+
g.to_url
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def klass
|
67
|
+
self.class
|
68
|
+
end
|
69
|
+
|
70
|
+
def x_values
|
71
|
+
case @style
|
72
|
+
when :minutes then 0..59
|
73
|
+
when :hours then 0..23
|
74
|
+
when :days then 1..31
|
75
|
+
when :weeks then 0..52 #week 0 == week 52 of last year, e.g. in 2009-01-01
|
76
|
+
when :months then 1..12
|
77
|
+
else raise "#{@style} is not supported"
|
78
|
+
end.to_a
|
79
|
+
end
|
80
|
+
|
81
|
+
#determines a unique color based on a name
|
82
|
+
def self.color_for(name)
|
83
|
+
name = name.inspect + "some randomness for fun"
|
84
|
+
hash = (name.hash % 1_000_000_000).to_s #get a hash of a constant size
|
85
|
+
colors = [hash[0..1], hash[2..3], hash[4..5]].map{|c| c.to_f / 100.0 * 16} #use 3 parts of the hash to get numbers from 0 to 15.99
|
86
|
+
palette = ('0'..'9').to_a + ('a'..'f').to_a #hex values 0..f
|
87
|
+
colors.map{|c| palette[c.floor].to_s * 2} * '' #each color is duplicated and the joined
|
88
|
+
end
|
89
|
+
|
90
|
+
def interval_for(time)
|
91
|
+
interval_word = {:minutes=>:hour,:hours=>:day,:days=>:month,:weeks=>:year,:months=>:year}[@style]
|
92
|
+
raise "style #{@style} is not supported" unless interval_word
|
93
|
+
|
94
|
+
start = klass.at_beginning_of_interval(time, interval_word)
|
95
|
+
ende = start + 1.send(interval_word) - 1.second
|
96
|
+
[start, ende]
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.at_beginning_of_interval(time, interval_type)
|
100
|
+
#simple substraction does not (seem) to work for long intervals (summer/winter time ?)
|
101
|
+
#and at_beginning_of_hour is not defined
|
102
|
+
if [:year, :month, :week, :day].include? interval_type
|
103
|
+
time.to_date.send("at_beginning_of_#{interval_type}")
|
104
|
+
else
|
105
|
+
time - (time.to_i % 1.send(interval_type))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.filled_and_sorted_values(values, keys)
|
110
|
+
array = fill_up_values(values, keys)
|
111
|
+
array.sort.map(&:last)
|
112
|
+
end
|
113
|
+
|
114
|
+
#values is array or hash with integer or string keys
|
115
|
+
def self.fill_up_values(values, expected_keys)
|
116
|
+
values = values.map{|k,v| [k.to_i, v]}
|
117
|
+
expected_keys.each{|k| values += [[k,0]] unless values.assoc(k)}
|
118
|
+
values.sort
|
119
|
+
end
|
120
|
+
|
121
|
+
def distribute_evently(values, num_steps)
|
122
|
+
min = values.min
|
123
|
+
max = values.max
|
124
|
+
step = (max-min) / (num_steps-1).to_f
|
125
|
+
(0...num_steps).map{|i| (step*i + min).to_f.round}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
2
|
+
|
3
|
+
describe DBGraph::Line do
|
4
|
+
describe "minutes" do
|
5
|
+
before :all do
|
6
|
+
Product.delete_all
|
7
|
+
Product.create!(:created_at=>"2009-01-01 10:59:59")
|
8
|
+
Product.create!(:created_at=>"2009-01-01 10:59:59")
|
9
|
+
|
10
|
+
Product.create!(:created_at=>"2009-01-01 11:00:00")
|
11
|
+
Product.create!(:created_at=>"2009-01-01 11:10:10")
|
12
|
+
Product.create!(:created_at=>"2009-01-01 11:10:20")
|
13
|
+
Product.create!(:created_at=>"2009-01-01 11:59:59")
|
14
|
+
|
15
|
+
Product.create!(:created_at=>"2009-01-01 12:00:00")
|
16
|
+
Product.create!(:created_at=>"2009-01-01 12:00:00")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "collects from one hour when at is set" do
|
20
|
+
line = DBGraph::Line.new(:minutes, :at=>Time.parse('2009-01-01 11:15:16'))
|
21
|
+
line.count(Product, :created_at).should == {"0"=>1,"10"=>2,"59"=>1}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "collects from all hours when at is not set" do
|
25
|
+
@line = DBGraph::Line.new(:minutes)
|
26
|
+
@line.count(Product, :created_at).should == {"59"=>3,"0"=>3,"10"=>2}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "hours" do
|
31
|
+
before :all do
|
32
|
+
Product.delete_all
|
33
|
+
Product.create!(:created_at=>"2009-01-01 23:59:59")
|
34
|
+
|
35
|
+
Product.create!(:created_at=>"2009-01-02 00:00:00")
|
36
|
+
Product.create!(:created_at=>"2009-01-02 10:11:12")
|
37
|
+
Product.create!(:created_at=>"2009-01-02 10:59:12")
|
38
|
+
Product.create!(:created_at=>"2009-01-02 13:11:12")
|
39
|
+
|
40
|
+
Product.create!(:created_at=>"2009-01-03 00:00:00")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "collects from one day when at is set" do
|
44
|
+
@line = DBGraph::Line.new(:hours, :at=>Time.parse('2009-01-02 14:15:16'))
|
45
|
+
@line.count(Product, :created_at).should == {"0"=>1,"10"=>2,"13"=>1}
|
46
|
+
end
|
47
|
+
|
48
|
+
it "collects from all days when at is not set" do
|
49
|
+
@line = DBGraph::Line.new(:hours)
|
50
|
+
@line.count(Product, :created_at).should == {"23"=>1,"0"=>2,"10"=>2,"13"=>1}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "days" do
|
55
|
+
before :all do
|
56
|
+
Product.delete_all
|
57
|
+
Product.create!(:created_at=>"2009-03-31 23:59:59")
|
58
|
+
|
59
|
+
Product.create!(:created_at=>"2009-04-01 00:00:00")
|
60
|
+
Product.create!(:created_at=>"2009-04-10 13:11:12")
|
61
|
+
Product.create!(:created_at=>"2009-04-30 23:59:59")
|
62
|
+
Product.create!(:created_at=>"2009-04-30 23:59:59")
|
63
|
+
|
64
|
+
Product.create!(:created_at=>"2009-05-01 00:00:00")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "collects from one onth when at is set" do
|
68
|
+
@line = DBGraph::Line.new(:days, :at=>Time.parse('2009-04-02 14:15:16'))
|
69
|
+
@line.count(Product, :created_at).should == {"1"=>1,"10"=>1,"30"=>2}
|
70
|
+
end
|
71
|
+
|
72
|
+
it "collects from all years when at is not set" do
|
73
|
+
@line = DBGraph::Line.new(:days)
|
74
|
+
@line.count(Product, :created_at).should == {"1"=>2,"10"=>1,"30"=>2,"31"=>1}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "weeks" do
|
79
|
+
before :all do
|
80
|
+
Product.delete_all
|
81
|
+
Product.create!(:created_at=>"2008-12-31 23:59:59")
|
82
|
+
|
83
|
+
Product.create!(:created_at=>"2009-01-01 00:00:00")
|
84
|
+
Product.create!(:created_at=>"2009-05-31 13:11:12")
|
85
|
+
Product.create!(:created_at=>"2009-05-31 13:11:11")
|
86
|
+
Product.create!(:created_at=>"2009-12-31 23:59:59")
|
87
|
+
|
88
|
+
Product.create!(:created_at=>"2010-01-01 00:00:00")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "collects from one year when at is set" do
|
92
|
+
@line = DBGraph::Line.new(:weeks, :at=>Time.parse('2009-01-02 14:15:16'))
|
93
|
+
@line.count(Product, :created_at).should == {"0"=>1,"22"=>2,"52"=>1}
|
94
|
+
end
|
95
|
+
|
96
|
+
it "collects from all years when at is not set" do
|
97
|
+
@line = DBGraph::Line.new(:weeks)
|
98
|
+
@line.count(Product, :created_at).should == {"0"=>2,"22"=>2,"52"=>2}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "months" do
|
103
|
+
before :all do
|
104
|
+
Product.delete_all
|
105
|
+
Product.create!(:created_at=>"2008-12-31 23:59:59")
|
106
|
+
|
107
|
+
Product.create!(:created_at=>"2009-01-01 00:00:00")
|
108
|
+
Product.create!(:created_at=>"2009-05-31 13:11:12")
|
109
|
+
Product.create!(:created_at=>"2009-05-31 13:11:11")
|
110
|
+
Product.create!(:created_at=>"2009-12-31 23:59:59")
|
111
|
+
|
112
|
+
Product.create!(:created_at=>"2010-01-01 00:00:00")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "collects from one year when at is set" do
|
116
|
+
@line = DBGraph::Line.new(:months, :at=>Time.parse('2009-01-02 14:15:16'))
|
117
|
+
@line.count(Product, :created_at).should == {"1"=>1,"5"=>2,"12"=>1}
|
118
|
+
end
|
119
|
+
|
120
|
+
it "collects from all years when at is not set" do
|
121
|
+
@line = DBGraph::Line.new(:months)
|
122
|
+
@line.count(Product, :created_at).should == {"1"=>2,"5"=>2,"12"=>2}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe :add do
|
127
|
+
it "accepts options for count" do
|
128
|
+
Product.delete_all
|
129
|
+
3.times{Product.create!}
|
130
|
+
2.times{Product.create!(:created_at=>'2009-02-02')}
|
131
|
+
3.times{Product.create!}
|
132
|
+
|
133
|
+
line = DBGraph::Line.new(:months)
|
134
|
+
line.add(Product, :created_at, :conditions=>"MONTH(created_at)=2")
|
135
|
+
line.data.values.first.should == {"2"=>2}
|
136
|
+
end
|
137
|
+
|
138
|
+
it "supports custom labels" do
|
139
|
+
line = DBGraph::Line.new(:months)
|
140
|
+
line.add(Product, :created_at, :label=>'ToC')
|
141
|
+
line.data['ToC'].should_not be_nil
|
142
|
+
end
|
143
|
+
|
144
|
+
it "adds the collected data to a hash" do
|
145
|
+
line = DBGraph::Line.new(:months)
|
146
|
+
line.add(Product, :created_at)
|
147
|
+
line.data['Product created_at'].should_not be_nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe :x_labels do
|
152
|
+
it "has minutes with gaps for readability" do
|
153
|
+
line = DBGraph::Line.new(:minutes)
|
154
|
+
gaps = [''] * 9
|
155
|
+
line.x_labels.should == [0,gaps,10,gaps,20,gaps,30,gaps,40,gaps,50,gaps].flatten
|
156
|
+
end
|
157
|
+
|
158
|
+
it "has all hours" do
|
159
|
+
line = DBGraph::Line.new(:hours)
|
160
|
+
line.x_labels.should == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
|
161
|
+
end
|
162
|
+
|
163
|
+
it "has days with gaps for readability" do
|
164
|
+
line = DBGraph::Line.new(:days)
|
165
|
+
gaps = ['','','','']
|
166
|
+
line.x_labels.should == [gaps,5,gaps,10,gaps,15,gaps,20,gaps,25,gaps,30,''].flatten
|
167
|
+
end
|
168
|
+
|
169
|
+
it "has weeks with gaps for readability" do
|
170
|
+
line = DBGraph::Line.new(:weeks)
|
171
|
+
gaps = [''] * 9
|
172
|
+
line.x_labels.should == [0,gaps,10,gaps,20,gaps,30,gaps,40,gaps,50,'',''].flatten
|
173
|
+
end
|
174
|
+
|
175
|
+
it "has all months" do
|
176
|
+
line = DBGraph::Line.new(:months)
|
177
|
+
line.x_labels.should == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe :y_labels do
|
182
|
+
it "has even values as y labels" do
|
183
|
+
Product.should_receive(:count).and_return({"0"=>1,"1"=>3,"2"=>3,"23"=>9})
|
184
|
+
line = DBGraph::Line.new(:hours)
|
185
|
+
line.add(Product, :created_at)
|
186
|
+
line.y_labels.should == [0,1,2,3,4,5,6,7,8,9]
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe :fill_up_values do
|
191
|
+
it "adds 0 for every non-filled value" do
|
192
|
+
data = [["1",2], ["3",3]]
|
193
|
+
expected_keys = [1,2,3,4,5]
|
194
|
+
filled = DBGraph::Line.send(:fill_up_values, data, expected_keys)
|
195
|
+
filled.should == [[1,2], [2,0], [3,3], [4,0], [5,0]]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe :filled_and_sorted_values do
|
200
|
+
it "fills/sorts the values" do
|
201
|
+
data = {"1"=>2, "3"=>3, "10"=>4}
|
202
|
+
expected_keys = [1,2,3,4,5,6,7,8,9,10]
|
203
|
+
filled = DBGraph::Line.send(:filled_and_sorted_values, data, expected_keys)
|
204
|
+
filled.should == [2, 0, 3, 0, 0, 0, 0, 0, 0, 4]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe :color_for do
|
209
|
+
it "returns the same color for the same names" do
|
210
|
+
c1 = DBGraph::Line.send(:color_for,'User found_at')
|
211
|
+
c2 = DBGraph::Line.send(:color_for,'User found_at')
|
212
|
+
c1.should == c2
|
213
|
+
end
|
214
|
+
|
215
|
+
it "returns different colors for different names" do
|
216
|
+
c1 = DBGraph::Line.send(:color_for,'User found_at')
|
217
|
+
c2 = DBGraph::Line.send(:color_for,'User created_at')
|
218
|
+
c1.should_not == c2
|
219
|
+
end
|
220
|
+
|
221
|
+
it "returns a color for empty/nil/[] names" do
|
222
|
+
[nil,[],'',' '].each do |value|
|
223
|
+
DBGraph::Line.send(:color_for,value).length.should == 6
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe :url do
|
229
|
+
it "can be called with 3 arguments" do
|
230
|
+
url = DBGraph::Line.url(:weeks, Product, :created_at)
|
231
|
+
url.should =~ /^http/
|
232
|
+
end
|
233
|
+
|
234
|
+
it "can be called with at option" do
|
235
|
+
url = DBGraph::Line.url(:weeks, Product, :created_at, :at=>Time.now)
|
236
|
+
url.should =~ /^http/
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/test_model.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
`mysqladmin create grosser_db_graph_test -u build` if ENV["RUN_CODE_RUN"]
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection({
|
4
|
+
:adapter => "mysql",
|
5
|
+
:database => "grosser_db_graph_test",
|
6
|
+
:username => ENV["RUN_CODE_RUN"] ? 'build' : 'root'
|
7
|
+
})
|
8
|
+
|
9
|
+
ActiveRecord::Schema.define(:version => 1) do
|
10
|
+
create_table :products, :force=>true do |t|
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Product < ActiveRecord::Base
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: db_graph
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Grosser
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-13 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: gchartrb
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activerecord
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description:
|
46
|
+
email: grosser.michael@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.markdown
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- README.markdown
|
56
|
+
- Rakefile
|
57
|
+
- VERSION
|
58
|
+
- db_graph.gemspec
|
59
|
+
- exmaples/multi_line_graph.rb
|
60
|
+
- lib/db_graph/line.rb
|
61
|
+
- spec/db_graph/line_spec.rb
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/test_model.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/grosser/db_graph
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --charset=UTF-8
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: AR generate beautiful graphs from date fields, in 1 LOC
|
92
|
+
test_files:
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
- spec/db_graph/line_spec.rb
|
95
|
+
- spec/test_model.rb
|