grosser-db_graph 0.1.2
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/README.markdown +44 -0
- data/Rakefile +24 -0
- data/VERSION.yml +4 -0
- data/lib/db_graph/line.rb +112 -0
- data/spec/db_graph/line_spec.rb +218 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/test_model.rb +15 -0
- metadata +90 -0
data/README.markdown
ADDED
@@ -0,0 +1,44 @@
|
|
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
|
+
|
10
|
+
Install
|
11
|
+
=======
|
12
|
+
As Gem:
|
13
|
+
sudo gem install grosser-db_graph -s http://gems.github.com/
|
14
|
+
|
15
|
+
Or as Rails plugin:
|
16
|
+
sudo gem install gchartrb
|
17
|
+
./script/plugins install git://github.com/grosser/db_graph.git
|
18
|
+
|
19
|
+
|
20
|
+
Usage
|
21
|
+
=====
|
22
|
+
#all hours/days/weeks/months
|
23
|
+
g = DBGraph::Line.new(:weeks)
|
24
|
+
|
25
|
+
#hours/days/weeks/months in a selected interval (e.g. in 1 year for months)
|
26
|
+
g = DBGraph::Line.new(:weeks, :at=>Time.parse('2009-01-02 14:15:16'))
|
27
|
+
|
28
|
+
g.add(User, :created_at)
|
29
|
+
g.add(Item, :sold_at, :label=>'Things we sold')
|
30
|
+
g.add(Product, :sold_at, :conditions=>['merchandise = ?',false])
|
31
|
+
...
|
32
|
+
g.to_url --> google chart url with all your data as line graph
|
33
|
+
|
34
|
+
We got :minutes, :hours, :days, :weeks, :months and seconds/years can be added if someone needs them...
|
35
|
+
|
36
|
+
TODO
|
37
|
+
====
|
38
|
+
- weeks/months from beginning of data (->all years)
|
39
|
+
|
40
|
+
Author
|
41
|
+
======
|
42
|
+
[Michael Grosser](http://pragmatig.wordpress.com)
|
43
|
+
grosser.michael@gmail.com
|
44
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
desc "Run all specs in spec directory"
|
2
|
+
task :default do |t|
|
3
|
+
options = "--colour --format progress --loadby --reverse"
|
4
|
+
files = FileList['spec/**/*_spec.rb']
|
5
|
+
system("spec #{options} #{files}")
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'jeweler'
|
11
|
+
project_name = 'db_graph'
|
12
|
+
Jeweler::Tasks.new do |gem|
|
13
|
+
gem.name = project_name
|
14
|
+
gem.summary = "AR generate beautiful graphs from date fields, in 1 LOC"
|
15
|
+
gem.email = "grosser.michael@gmail.com"
|
16
|
+
gem.homepage = "http://github.com/grosser/#{project_name}"
|
17
|
+
gem.authors = ["Michael Grosser"]
|
18
|
+
gem.add_dependency ['gchartrb']
|
19
|
+
gem.add_dependency ['activesupport']
|
20
|
+
gem.add_dependency ['activerecord']
|
21
|
+
end
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
24
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,112 @@
|
|
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, self.class.filled_and_sorted_values(hash, x_values), random_color)
|
37
|
+
end
|
38
|
+
line.axis :x, :labels => x_labels
|
39
|
+
line.axis :y, :labels => y_labels
|
40
|
+
end.to_url
|
41
|
+
end
|
42
|
+
|
43
|
+
def x_labels
|
44
|
+
case @style
|
45
|
+
when :days then x_values.map{|x|x%5==0 ? x : ''}
|
46
|
+
when :weeks, :minutes then x_values.map{|x|x%10==0 ? x : ''}
|
47
|
+
else x_values
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def y_labels
|
52
|
+
values = []
|
53
|
+
data.each{|name,hash|values += self.class.filled_and_sorted_values(hash, x_values)}
|
54
|
+
distribute_evently(values, NUM_Y_LABELS)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def x_values
|
60
|
+
case @style
|
61
|
+
when :minutes then 0..59
|
62
|
+
when :hours then 0..23
|
63
|
+
when :days then 1..31
|
64
|
+
when :weeks then 0..52 #week 0 == week 52 of last year, e.g. in 2009-01-01
|
65
|
+
when :months then 1..12
|
66
|
+
else raise "#{@style} is not supported"
|
67
|
+
end.to_a
|
68
|
+
end
|
69
|
+
|
70
|
+
def random_color
|
71
|
+
[1,2,3].map{ (('0'..'9').to_a + ('a'..'f').to_a)[rand(16)] * 2 } * ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def interval_for(time)
|
75
|
+
interval_word = {:minutes=>:hour,:hours=>:day,:days=>:month,:weeks=>:year,:months=>:year}[@style]
|
76
|
+
raise "style #{@style} is not supported" unless interval_word
|
77
|
+
|
78
|
+
start = self.class.at_beginning_of_interval(time, interval_word)
|
79
|
+
ende = start + 1.send(interval_word) - 1.second
|
80
|
+
[start, ende]
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.at_beginning_of_interval(time, interval_type)
|
84
|
+
#simple substraction does not (seem) to work for long intervals (summer/winter time ?)
|
85
|
+
#and at_beginning_of_hour is not defined
|
86
|
+
if [:year, :month, :week, :day].include? interval_type
|
87
|
+
time.to_date.send("at_beginning_of_#{interval_type}")
|
88
|
+
else
|
89
|
+
time - (time.to_i % 1.send(interval_type))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.filled_and_sorted_values(values, keys)
|
94
|
+
array = fill_up_values(values, keys)
|
95
|
+
array.sort.map(&:last)
|
96
|
+
end
|
97
|
+
|
98
|
+
#values is array or hash with integer or string keys
|
99
|
+
def self.fill_up_values(values, expected_keys)
|
100
|
+
values = values.map{|k,v| [k.to_i, v]}
|
101
|
+
expected_keys.each{|k| values += [[k,0]] unless values.assoc(k)}
|
102
|
+
values.sort
|
103
|
+
end
|
104
|
+
|
105
|
+
def distribute_evently(values, num_steps)
|
106
|
+
min = values.min
|
107
|
+
max = values.max
|
108
|
+
step = (max-min) / (num_steps-1).to_f
|
109
|
+
(0...num_steps).map{|i| (step*i + min).to_f.round}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,218 @@
|
|
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 :random_color do
|
209
|
+
before do
|
210
|
+
@line = DBGraph::Line.new(:months)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "includes pairs of colors" do
|
214
|
+
@line.should_receive(:rand).and_return 0,2,10
|
215
|
+
@line.send(:random_color).should == '0022aa'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/test_model.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection({
|
2
|
+
:adapter => "mysql",
|
3
|
+
:database => "db_graph_test",
|
4
|
+
:user => 'root',
|
5
|
+
:password => 'root'
|
6
|
+
})
|
7
|
+
|
8
|
+
ActiveRecord::Schema.define(:version => 1) do
|
9
|
+
create_table :products, :force=>true do |t|
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Product < ActiveRecord::Base
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grosser-db_graph
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Grosser
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-24 00:00:00 -07: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
|
+
- README.markdown
|
55
|
+
- Rakefile
|
56
|
+
- VERSION.yml
|
57
|
+
- lib/db_graph/line.rb
|
58
|
+
- spec/db_graph/line_spec.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
- spec/test_model.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/grosser/db_graph
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.2.0
|
84
|
+
signing_key:
|
85
|
+
specification_version: 2
|
86
|
+
summary: AR generate beautiful graphs from date fields, in 1 LOC
|
87
|
+
test_files:
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- spec/db_graph/line_spec.rb
|
90
|
+
- spec/test_model.rb
|