18 Aug
Got another comment, this time asking about all kinds of things :
Plotting Points
X Axis and Y Axis min and max ranges
Coloring the X and Y Axis
Coloring the X and Y gridlines
Here is the graph we are after in this example:
More Open Flash Chart II examples.
And here is the code (the controller):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class TestItController < ApplicationController
def index
@graph = open_flash_chart_object(600 ,300 ," /test_it/graph_code " )
end
def graph_code
chart = OpenFlashChart .new
title = Title .new(" Scatter points " )
chart.set_title(title)
scatter = Scatter .new(' #FFD800 ' , 10 ) # color, dot size
scatter.values = [
ScatterValue .new(50 ,30 ),
ScatterValue .new(305 ,400 ),
ScatterValue .new(61 ,500 ,15 ), # x, y, dot size
ScatterValue .new(600 ,550 ),
ScatterValue .new(459 ,300 ),
ScatterValue .new(180 ,789 )
]
chart.add_element(scatter)
x = XAxis .new
x.set_range(0 , 650 , 100 ) #min, max, steps
# alternatively, you can use x.set_range(0,65000) and x.set_step(10000)
x.colour = ' #00FF00 '
# have to set the x axis labels because of scatter bug here - http://sourceforge.net/forum/message.php?msg_id=4812326
x.set_grid_colour(' #00F0FF ' )
chart.set_x_axis(x)
y = YAxis .new
y.set_range(0 ,800 ,200 )
y.colour = ' #FF0000 '
y.set_grid_colour(' #FF00FF ' )
chart.set_y_axis(y)
render :text => chart.to_s
end
end
And in your view (index.html.erb):
1
2
3
4
<script type=" text/javascript " src=" /javascripts/swfobject.js " ></ script>
<%= @graph %>
Note - The X Axis is not rendering properly, this is being discussed in the OFC Forums .
Good Luck!
13 Aug
Have you ever encountered this error?
wrong constant name X::YAssociationExtension
I found this error when dealing with acts_as_versioned for one my models. I would have found it eventually with any association I would have setup in this case, so it is not acts_as_versioned's fault.
I have an application with various parts so I create some of my models like this:
1
2
./script/generate model module_name::model_name
So the fix is pretty simple, instead of winding up with ModuleName::ModelAssociationExtension or whatever, you want your extention module name to be ModelAssociationExtension.
Here is the method where the code breaks for me:
1
2
3
4
5
6
7
8
9
10
11
12
13
def create_extension_modules (association_id, block_extension, extensions)
if block_extension
extension_module_name = " #{ self .to_s} #{ association_id.to_s.camelize} AssociationExtension "
silence_warnings do
Object .const_set(extension_module_name, Module .new(&block_extension))
end
Array(extensions).push(extension_module_name.constantize)
else
Array(extensions)
end
end
Here is the fix, on line 3, you will note the demodulize addition:
1
2
3
4
5
6
7
8
9
10
11
12
13
def create_extension_modules (association_id, block_extension, extensions)
if block_extension
extension_module_name = " #{ self .to_s.demodulize} #{ association_id.to_s.camelize} AssociationExtension "
silence_warnings do
Object .const_set(extension_module_name, Module .new(&block_extension))
end
Array(extensions).push(extension_module_name.constantize)
else
Array(extensions)
end
end
I threw the corrected code into a library - RAILS_ROOT/lib/fix_active_record_create_extension_for_modules.rb. Make sure to open up the necessary modules to overwrite the method itself, I.e., like this:
1
2
3
4
5
6
7
8
module ActiveRecord
module Associations
module ClassMethods
# the code above fits right here
end
end
end
Short and sweet, let me know if you have a better method for handling this.
05 Aug
Got another comment asking about diagonal x axis labels . This example is based on teethgrinder's line graph example and the new portions are based on teethgrinder's x-axis rotation example .
Here is the graph we are after in this example:
More Open Flash Chart II examples.
And here is the code (the controller):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class TestItController < ApplicationController
def index
@graph = open_flash_chart_object(600 ,300 ," /test_it/graph_code " )
end
def graph_code
# based on this example - http://teethgrinder.co.uk/open-flash-chart-2/data-lines-2.php
# and parts from this example - http://teethgrinder.co.uk/open-flash-chart-2/x-axis-labels-3.php
title = Title .new(" Multiple Lines " )
data1 = []
data2 = []
data3 = []
10 .times do |x|
data1 << rand(5 ) + 1
data2 << rand(6 ) + 7
data3 << rand(5 ) + 14
end
line_dot = LineDot .new
line_dot.width = 4
line_dot.colour = ' #DFC329 '
line_dot.dot_size = 5
line_dot.values = data1
line_hollow = LineHollow .new
line_hollow.width = 1
line_hollow.colour = ' #6363AC '
line_hollow.dot_size = 5
line_hollow.values = data2
line = Line .new
line.width = 1
line.colour = ' #5E4725 '
line.dot_size = 5
line.values = data3
# Added these lines since the previous tutorial
tmp = []
x_labels = XAxisLabels .new
x_labels.set_vertical()
%w( one two three four five six seven eight nine ten ) .each do |text|
tmp << XAxisLabel .new(text, ' #0000ff ' , 20 , ' diagonal ' )
end
x_labels.labels = tmp
x = XAxis .new
x.set_labels(x_labels)
# new up to here ...
y = YAxis .new
y.set_range(0 ,20 ,5 )
x_legend = XLegend .new(" MY X Legend " )
x_legend.set_style(' {font-size: 20px; color: #778877} ' )
y_legend = YLegend .new(" MY Y Legend " )
y_legend.set_style(' {font-size: 20px; color: #770077} ' )
chart =OpenFlashChart .new
chart.set_title(title)
chart.set_x_legend(x_legend)
chart.set_y_legend(y_legend)
chart.x_axis = x # Added this line since the previous tutorial
chart.y_axis = y
chart.add_element(line_dot)
chart.add_element(line_hollow)
chart.add_element(line)
render :text => chart.to_s
end
end
And in your view (index.html.erb):
1
2
3
4
<script type=" text/javascript " src=" /javascripts/swfobject.js " ></ script>
<%= @graph %>
Good Luck!
05 Aug
I just got comment asking how one would go about doing a many to many relation in this dynamic select box example . For example, what if an artist belongs to multiple genres. Here we go:
The original tutorial .
Create your models and build your migrations:
1
2
3
4
5
ruby script/generate model genre name:string
ruby script/generate model artist name:string # no genre_id here, moved to association table
ruby script/generate model song title:string artist_id:integer
ruby script/generate model artist_association artist_id:integer genre_id:integer
Populate your genres, artists and songs through a migration:
1
2
ruby script/generate migration create_hierarchy
Contents of migration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class CreateHierarchy < ActiveRecord ::Migration
def self .up
# same genres as before
g1 = Genre .create(:name => " Genre 1 " )
g2 = Genre .create(:name => " Genre 2 " )
g3 = Genre .create(:name => " Genre 3 " )
# same artists as before, but without a genre_id
a1 = Artist .create(:name => " Artist 1 " )
a2 = Artist .create(:name => " Artist 2 " )
a3 = Artist .create(:name => " Artist 3 " )
a4 = Artist .create(:name => " Artist 4 " )
a5 = Artist .create(:name => " Artist 5 " )
a6 = Artist .create(:name => " Artist 6 " )
# now set which artists belong to which genres
# Artist 1 belongs to all three genres
ArtistAssociation .create(:genre_id => g1.id, :artist_id => a1.id)
ArtistAssociation .create(:genre_id => g2.id, :artist_id => a1.id)
ArtistAssociation .create(:genre_id => g3.id, :artist_id => a1.id)
# the rest of the artists only belong to one association
ArtistAssociation .create(:genre_id => g1.id, :artist_id => a2.id)
ArtistAssociation .create(:genre_id => g2.id, :artist_id => a3.id)
ArtistAssociation .create(:genre_id => g2.id, :artist_id => a4.id)
ArtistAssociation .create(:genre_id => g3.id, :artist_id => a5.id)
ArtistAssociation .create(:genre_id => g3.id, :artist_id => a6.id)
Song .create(:title => " Song 1 " , :artist_id => a1.id)
Song .create(:title => " Song 2 " , :artist_id => a1.id)
Song .create(:title => " Song 3 " , :artist_id => a2.id)
Song .create(:title => " Song 4 " , :artist_id => a2.id)
Song .create(:title => " Song 5 " , :artist_id => a3.id)
Song .create(:title => " Song 6 " , :artist_id => a3.id)
Song .create(:title => " Song 7 " , :artist_id => a4.id)
Song .create(:title => " Song 8 " , :artist_id => a4.id)
Song .create(:title => " Song 9 " , :artist_id => a5.id)
Song .create(:title => " Song 10 " , :artist_id => a5.id)
Song .create(:title => " Song 11 " , :artist_id => a6.id)
Song .create(:title => " Song 12 " , :artist_id => a6.id)
end
def self .down
# you can fill this in if you want.
end
end
So now we need to populate the database:
Now we need to modify our models to set up the associations.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Genre < ActiveRecord ::Base
has_many :artist_associations
has_many :artists , :through => :artist_associations
# CAN"T NEST HMTs ..... has_many :songs, :through => :artists
# do it by hand ... argh
def songs
artists.map{|a| a.songs}.flatten
end
end
class Artist < ActiveRecord ::Base
has_many :artist_associations
has_many :genres , :through => :artist_associations
has_many :songs
end
class ArtistAssociation < ActiveRecord ::Base
belongs_to :artist
belongs_to :genre
end
That should be it for the many to many relationship.
Everything else is the same as in the last tutorial .
# the controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class TestItController < ApplicationController
def index
@genres = Genre .find(:all )
@artists = Artist .find(:all )
@songs = Song .find(:all )
end
def update_artists
# updates artists and songs based on genre selected
genre = Genre .find(params[:genre_id ])
artists = genre.artists
songs = genre.songs
render :update do |page|
page.replace_html ' artists ' , :partial => ' artists ' , :object => artists
page.replace_html ' songs ' , :partial => ' songs ' , :object => songs
end
end
def update_songs
# updates songs based on artist selected
artist = Artist .find(params[:artist_id ])
songs = artist.songs
render :update do |page|
page.replace_html ' songs ' , :partial => ' songs ' , :object => songs
end
end
end
Now as far as views go we have one view (index.html.erb) and two partials (_songs and _artists). Let's take a look at those:
# the _songs partial (_songs.html.erb):
1
2
3
<%= collection_select(nil , :song_id , songs, :id , :title ,
{:prompt => " Select a Song " }) %>
# the _artists partial (_artists.html.erb):
1
2
3
4
5
6
<%= collection_select(nil , :artist_id , artists, :id , :name ,
{:prompt => " Select an Artist " },
{:onchange => " #{ remote_function(:url => {:action => " update_songs " },
:with => " 'artist_id='+value " )} " }) %>
<br/>
# and last, but not least, the index view (index.html.erb):
1
2
3
4
5
6
7
8
9
<%= javascript_include_tag :defaults %>
<%= collection_select(nil, :genre_id, @genres, :id, :name,
{:prompt => " Select a Genre " },
{:onchange => " #{ remote_function(:url => {:action => " update_artists " },
:with => " 'genre_id='+value " )} " }) %>
<br/>
<div id=" artists " ><%= render :partial => ' artists ' , :object => @artists %> </div >
<div id=" songs " ><%= render :partial => ' songs ' , :object => @songs %> </div >
04 Aug
Got a comment asking about multiple graphs on the same page and if you need another controller or how that would all work . You only need one controller if you are going to have different graphs in the same view.
No graph for this example, just the code.
Open Flash Chart II examples.
Here is the code (the controller):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class TestItController < ApplicationController
def index
@graph1 = open_flash_chart_object(600 ,300 ," /test_it/graph_one " )
@graph2 = open_flash_chart_object(600 ,300 ," /test_it/graph_two " )
@graph3 = open_flash_chart_object(600 ,300 ," /test_it/graph_three " )
# and so on ...
end
def graph_one
... # put some OFC2 code here like in my examples
end
def graph_two
... # put some OFC2 code here
end
def graph_three
... # put some OFC2 code here
end
end
And in your view (index.html.erb):
1
2
3
4
5
6
<script type=" text/javascript " src=" /javascripts/swfobject.js " ></ script>
<%= @graph1 %><br / >
<%= @graph2 %> <br/ >
<%= @graph3 %> <br/ >
Good Luck!
01 Aug
Got another comment asking about creating a line graph . This example is based on teethgrinder's line graph example .
Here is the graph we are after in this example:
More Open Flash Chart II examples.
And here is the code (the controller):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class TestItController < ApplicationController
def index
@graph = open_flash_chart_object(600 ,300 ," /test_it/graph_code " )
end
def graph_code
# based on this example - http://teethgrinder.co.uk/open-flash-chart-2/data-lines-2.php
title = Title .new(" Multiple Lines " )
data1 = []
data2 = []
data3 = []
10 .times do |x|
data1 << rand(5 ) + 1
data2 << rand(6 ) + 7
data3 << rand(5 ) + 14
end
line_dot = LineDot .new
line_dot.text = " Line Dot "
line_dot.width = 4
line_dot.colour = ' #DFC329 '
line_dot.dot_size = 5
line_dot.values = data1
line_hollow = LineHollow .new
line_hollow.text = " Line Hollow "
line_hollow.width = 1
line_hollow.colour = ' #6363AC '
line_hollow.dot_size = 5
line_hollow.values = data2
line = Line .new
line.text = " Line "
line.width = 1
line.colour = ' #5E4725 '
line.dot_size = 5
line.values = data3
y = YAxis .new
y.set_range(0 ,20 ,5 )
x_legend = XLegend .new(" MY X Legend " )
x_legend.set_style(' {font-size: 20px; color: #778877} ' )
y_legend = YLegend .new(" MY Y Legend " )
y_legend.set_style(' {font-size: 20px; color: #770077} ' )
chart =OpenFlashChart .new
chart.set_title(title)
chart.set_x_legend(x_legend)
chart.set_y_legend(y_legend)
chart.y_axis = y
chart.add_element(line_dot)
chart.add_element(line_hollow)
chart.add_element(line)
render :text => chart.to_s
end
end
And in your view (index.html.erb):
1
2
3
4
<script type=" text/javascript " src=" /javascripts/swfobject.js " ></ script>
<%= @graph %>
Good Luck!