Open Flash Chart II - Point by Point plotting

August 18th, 2008 by charlie

Got another comment, this time asking about all kinds of things:
  1. Plotting Points
  2. X Axis and Y Axis min and max ranges
  3. Coloring the X and Y Axis
  4. 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!


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.


Open Flash Chart II - X Axis Label rotations

August 5th, 2008 by charlie

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!


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:
1
2

rake db:migrate
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>


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!


Open Flash Chart II - Line Graph

August 1st, 2008 by charlie

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

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.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

    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!


Open Flash Chart II - Horizontal Bar Graph

July 30th, 2008 by charlie

Just got another comment asking about making a horizontal bar chart. This example is based on teethgrinder's horizontal bar example. So you will need to get the latest plugin since this required that I add a few things as of this article.
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

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/horizontal-bar-chart.php
    title = Title.new("HBar Graph")

    hbar = HBar.new
    # could also do it one at a time with hbar.append_value(...) or
    # hbar.values << ...
    hbar.values = [HBarValue.new(0,4), HBarValue.new(4,8), HBarValue.new(8,11)]

    chart = OpenFlashChart.new
    chart.set_title(title)
    chart.add_element(hbar)

    x = XAxis.new
    x.set_offset(false)
    x.set_labels(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])
    chart.set_x_axis(x)

    y = YAxis.new
    y.set_offset(true)
    y.set_labels(["Make garden look sexy","Paint house","Move into house"])
    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 %>



Good Luck!


Open Flash Chart II - Pie Chart

July 29th, 2008 by charlie

Just got a comment asking for a pie chart example, so here is an example. This example is based on teethgrinder's pie chart example for php.
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

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/pie-chart.php
    title = Title.new("Pie Chart Example For Chipster")

    pie = Pie.new
    pie.start_angle = 35
    pie.animate = true
    pie.tooltip = '#val# of #total#<br>#percent# of 100%'
    pie.colours = ["#d01f3c", "#356aa0", "#C79810"]
    pie.values  = [2,3, PieValue.new(6.5,"Hello (6.5)")]

    chart = OpenFlashChart.new
    chart.title = title
    chart.add_element(pie)

    chart.x_axis = nil

    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!


Just got a comment that says tooltips are not working properly, so I decided to do an example for you guys (and gals). This example is based on teethgrinder's tooltip example.
Here is the graph we are after in this example:


More Open Flash Chart II examples.

And here is the code (the controller):
NOTE: You will need the latest plugin and open-flash-chart.swf (as of this article) for the tooltips to register properly.
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

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/tooltip.php
    title = Title.new("MultiBar Tooltip")

    bar = Bar.new
    bar.values  = [9,8,7,6,5,4,3,2,1]
    bar.tooltip = "Title Bar l<br>val = #val#"
    bar.colour  = '#47092E'

    # NOTE: you can use obj.variable=() or obj.set_variable() interchangeably

    bar2 = Bar.new
    bar2.set_tooltip("Spoon {#val#}<br>Title Bar 2")
    bar2.set_colour('#CC2A43')

    vals = [1,2,3,4]

    tmp = BarValue.new(5)
    tmp.set_colour('#000000')
    tmp.set_tooltip("Spoon {#val#}<br>Title Bar 2<br>Override bar 2 tooltip<br>Special data point")
    vals << tmp
    vals << [6,7,8,9]
    vals = vals.flatten

    bar2.values = vals

    t = Tooltip.new
    t.set_shadow(false)
    t.stroke = 5
    t.colour = '#6E604F'
    t.set_background_colour("#BDB396")
    t.set_title_style("{font-size: 14px; color: #CC2A43;}")
    t.set_body_style("{font-size: 10px; font-weight: bold; color: #000000;}")

    chart = OpenFlashChart.new
    chart.title = title
    chart.add_element(bar)
    chart.add_element(bar2)
    chart.set_tooltip(t)

    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!


Just got Archie Smuts comment asking how to populate a Open Flash Chart graph using results from a database.

Just for reference, the code that follows represents this graph:


Examples for version 2 are here.

Using the new version of Open Flash Chart, here is an example for you to follow:
  • Start a rails app and install the plugin per these instructions.
  • The results table that I am working with has these rows:
    1
    2
    3
    4
    5
    6
    
    
    Result.create(:student_name => "Jack", :subject => "History", :test_score => 97
    Result.create(:student_name => "Jack", :subject => "Science", :test_score => 85)
    Result.create(:student_name => "Jill", :subject => "History", :test_score => 92)
    Result.create(:student_name => "Jill", :subject => "Science", :test_score => 57)
    
    
  • Create a controller, mine is test_it:
    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
    
    
    class TestItController < ApplicationController
      def index
        @graph = open_flash_chart_object(600,300,"/test_it/graph_code")
      end
    
      def graph_code
        # we will have bars for each student subject combo
        bars   = []
    
        # random colors to chose from
        colours = ["#459a89", "#9a89f9"]
    
        # the results
        results = Result.find(:all)
    
        # group by subject and use subject as the key
        results.group_by(&:subject).each do |subject, result|
          # 3d bar graph, could be any bar graph though
          bar = Bar3d.new
          bar.set_key(subject, 3)
          bar.colour = colours[bars.size]
          bar.values = result.map(&:test_score)
          bars << bar
        end
    
        # some title
        title = Title.new("Test Results")
    
        # labels along the x axis, just hard code for now, but you would want to dynamically do this
        x_axis = XAxis.new
        x_axis.labels = ["Jack", "Jill"]
    
        # go to 100% since we are dealing with test results
        y_axis = YAxis.new
        y_axis.set_range(0, 100, 10)
    
        # setup the graph
        graph = OpenFlashChart.new
        graph.bg_colour = '#ffffcc'
        graph.title = title
        graph.x_axis = x_axis
        graph.y_axis = y_axis
        graph.elements = bars
    
        render :text => graph.to_s
      end
    end
    
    
  • Create a view, mine is index.html.erb for the test_it controller:
    1
    2
    3
    4
    
    
    <script type="text/javascript" src="/javascripts/swfobject.js"></script>
    <%= @graph %>
    
    

  • Hope that helps.

simpleCMS on github

July 24th, 2008 by charlie

Moved simpleCMS over to github.

There were quite a few changes that were required to get it working with rails 2.1, so they are in the repository now.
So to install, you pretty much follow the same instructions from before.

The only thing I have not completely resolved is the use of the simple_cms_item partial that sits in the plugin's app/views/shared directory. I tried forever to use append_view_path to share the partial over. That worked, as in it found the partial, but the application layout went away, so instead, you can just copy the partial to your RAILS_ROOT/app/views/shared directory for now.

Additionally, you can install it through github: script/plugin install git://github.com/pullmonkey/simple_cms.git
And of course, a lot of you have asked how to just plain download it, well you can do that here, find the download button and click :)

Let me know how it goes.

Ok, already, I heard ya :) The open flash chart (version 2 - OFC2) plugin is done (really just started) and it is out on github.

Examples for version 2 are here.

I rewrote the open flash chart plugin (started from scratch) to work with json like teethgrinder does here.
This time I think it is much slicker and a lot easier to work with.
I haven't tried much more than bar graphs, all the functionality is there for other types of graphs, just not tested.
Graph that this example produces:


So it is out there, and if you are willing to try it out, here is how:
  1. rails testing_ofc_2
  2. cd testing_ofc_2
  3. script/plugin install git://github.com/pullmonkey/open_flash_chart.git
  4. script/generate controller test_it
  5. Add the following to the test_it_controller.rb in RAILS_ROOT/app/controllers:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    
    class TestItController < ApplicationController
      def index
        @graph = open_flash_chart_object(600,300,"/test_it/graph_code")
      end
    
      def graph_code
        title = Title.new("MY TITLE")
        bar = BarGlass.new
        bar.set_values([1,2,3,4,5,6,7,8,9])
        chart = OpenFlashChart.new
        chart.set_title(title)
        chart.add_element(bar)
        render :text => chart.to_s
      end
    end
    
    
  6. Add the following to index.html.erb in RAILS_ROOT/app/views/test_it/:
    1
    2
    3
    4
    5
    
    
    <script type="text/javascript" src="/javascripts/swfobject.js"></script>
    <%= @graph %>
    
      
  7. Copy swfobject.js from the plugin's assets/ directory (will make this happen at install time later) to your RAILS_ROOT/public/javascripts directory
  8. Copy open-flash-chart.swf from the plugin's assets/ director to your RAILS_ROOT/public/ directory
  9. script/server
  10. Browse to http://localhost:3000/test_it
  11. Let me know how it goes, thanks.


Ruby on Rails - Multiple database connections

April 21st, 2008 by charlie

Found a need for this information while answering questions on railsforum.
So, let's say that we want to use two databases and let's even say that we want to use an Oracle database and a MySQL database. How can this be done? To start, we must decide which database will be our default database. In this scenario, I chose MySQL. Let's see what that looks like:
1
2
3
4
5
6
7
# in your database.yml file
development:
  adapter: mysql
  username: root
  password: 
  database: example_development

So we have all seen that before. Now all of our active record models will use this mysql connection.
But, I need to use data from an oracle database, so let's setup that connection:
1
2
3
4
5
6
7
8
9
10
11
12
13
# in your database.yml file
development:
  adapter: mysql
  username: root
  password: 
  database: example_development

oracle_development:
  adapter: oracle
  username: root
  password: 
  database: example_oracle_development

Neat, we have two development connections. Now we have to tell which models to use which connection. Well, actually, we just need to tell the oracle models to connect to oracle_development, all the other models will default to development. I have a model named user, and it's records are kept in an oracle database. Our user model looks like this initially:
1
2
3
4
#RAILSROOT/app/models/user.rb
class User < ActiveRecord::Base 
end

The line we need to add is this:
1
2
establish_connection :oracle_development

Even better, we can make this dynamic, so when we are in the test or production environment, we don't need to change the establish_connection line.
1
2
3
# use RAILS_ENV where RAILS_ENV is generally development, test or production
establish_connection "oracle_#{RAILS_ENV}"

So the final product could look something like this:

database.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dev_basics: &dev_basics
  username: root
  password: 

<% %w(development test production).each do |env| %>
<%= env %>:
  <<: *dev_basics
  adapter: mysql
  database: example_<%= env %>

oracle_<%= env %>:
  <<: *dev_basics
  adapter: oracle
  database: example_oracle_<%= env %>
<% end %>

Oracle model example

1
2
3
4
class User < ActiveRecord::Base 
  establish_connection "oracle_#{RAILS_ENV}"
end


That should be it.

Ok, great news. I have fixed a fairly large bug, Even better news, you probably never noticed it unless you were trying to output graphs via javascript, I.e., using graph.set_output_type("js").
Thanks go to Brandon, who provided an example of using javascript as the output type:

View Source Code
So if this was affecting you, then you will want to get the latest version of the plugin - Instructions.

Ruby - include? versus intersection

April 2nd, 2008 by charlie

After my last article about intersection and arrays, I got to thinking how this could apply elsewhere.
I decided to see if I could write a faster include?() method for Array using the intersection operator. So here is what I did:

1) Tested via irb (of course)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

[pullmonkey]$ irb
# build the array for conceptual testing
irb(main):003:0> a = [1,2,3]
=> [1, 2, 3]
# see how include?() does it
irb(main):004:0> a.include?(2)
=> true
irb(main):005:0> a.include?(4)
=> false
# see what could be done with intersect
irb(main):006:0> a & [2]
=> [2]
irb(main):007:0> (a & [2]).empty?
=> false
# this should return true, so negate it
irb(main):008:0> !(a & [2]).empty?
=> true
irb(main):009:0> !(a & [4]).empty?
=> false

2) Extended the Array class with the faster_include?() method:

1
2
3
4
5
6

class Array
  def faster_include?(n)
    !(self & [n]).empty?
  end
end

3) Wrote a performance test comparing elapsed time for true and false results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# size of the array
x = 4000000
# build the array
a = (1..x).to_a
p "Finding #{x/2} ..."
t1 = Time.now
p "include?() - returns true: #{a.include?(x/2)}"
t2 = Time.now
p "faster_include?() - returns true: #{a.faster_include?(x/2)}"
t3 = Time.now
p "include?() - returns false: #{a.include?(-50)}"
t4 = Time.now
p "faster_include?() - returns false: #{a.faster_include?(-50)}"
t5 = Time.now
p "Elapsed time for include?() returning true: #{t2 - t1}."
p "Elapsed time for faster_include?() returning true: #{t3 - t2}."
p "Elapsed time for include?() returning false: #{t4 - t3}."
p "Elapsed time for faster_include?() returning false: #{t5 - t4}."

4) Just to see if there was a difference I got results and here they are:

Attempt 1:
1
2
3
4
5
6
7
8
9
10

"Finding 2000000 ..."
"include?() - returns true: true"
"faster_include?() - returns true: true"
"include?() - returns false: false"
"faster_include?() - returns false: false"
"Elapsed time for include?() returning true: 0.308243."
"Elapsed time for faster_include?() returning true: 0.271465."
"Elapsed time for include?() returning false: 0.