Archive for the ‘How-to’ Category

Calling Oracle stored procedure from rails

Sometimes it is necessary to reuse existing logic from stored procedures. This line of code shows how to call a stored procedure in Oracle.

ActiveRecord::Base.connection.execute('BEGIN do_the_calculation; END;')

From pictures to picturables

This article tries to explain how to convert existing class in Ruby on Rails to a class that can be used in polymorphic association class. As the beginning, I do recommend to read article about polymorphic associations. It explains what they are and how they work.

The whole process will be described on classes Picture (represents picture) and Item (an item that needs a picture).

1. First of all, it is necessary to create columns for the pictures table. The best way is to use migrations. So, create file e.g. 013_convert_pictures_to_polymorph.rb in your db/migrate directory. It should contain something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ConvertPicturesToPolymorph < ActiveRecord::Migration
 
  def self.up
    # Change old item_id identifier to new picturable_id
    rename_column :pictures, :item_id, :picturable_id
    # Add type of association
    add_column :pictures, :picturable_type, :string, :length => 50
    # Fill in the type of association
    execute "update pictures set picturable_type = \"Item\""
  end
 
 
  def self.down
    # Bring it back
    rename_column :pictures, :picturable_id, :item_id
    remove_column :pictures, :picturable_type
  end
end

now run:

1
rake migrate

to create the columns.

2. Once the appropriate columns were created, it is necessary to change the Item class. Change the

1
  has_many  :pictures

to

1
  has_many  :pictures, :as => :picturable

3. Now change the Picture class. Change

1
  belongs_to :item

to

1
  belongs_to :picturable, :polymorphic => true

Make sure, there is no “item” left in the Picture class. If so, change it to picturable and make sure all picturables have the method you are using.

4. Creating a new class enriched by pictures is simple. Just add

1
  has_many  :pictures, :as => :picturable

to your class.

5. Last but not least, change your fixtures. The easiest way is to export the current data from your database. For this purpose I do use manage_fixtures plugin.

Good luck!

RSpec for Ruby on Rails

Behaviour driven development is currently in. The best ay how to get in touch with it is to setup your own environment and make few examples.Nevertheless, if you prefer to start with a bit of theory, go to http://behaviour-driven.org/.This article describes simple procedure to setup Rspec to work together with ruby on rails.

Installation of RSpec

The installation procedure described in documentation needed small improvement:

First of all, install the rspec gem

gem install -r rspec #mac users must sudo

Then install following gems:

  • rake # Runs the build script
  • rcov # Verifies that the code is 100% covered by specs
  • webgen # Generates the static HTML website
  • RedCloth # Required by webgen
  • syntax # Required by our own custom webgen extension to highlight ruby code
  • diff-lcs # Required if you use the -diff switch
  • win32console # Required by the -colour switch if you‘re on Windows
  • meta_project # Required in order to make releases at RubyForge
  • heckle # Required if you use the -heckle switch
  • hpricot # Used for parsing HTML from the HTML output formatter in RSpec’s own specs

Then continue with these steps:

svn co svn://rubyforge.org/var/svn/rspec/trunk rspec
cd rspec
rake install_dependencies
cd example_rails_app
export RSPEC_RAILS_VERSION=1.2.3
rake rspec:generate_mysql_config
mysql -u root -p &lt; db/mysql_setup.sql
cd ..change example_rails_app/config/database.yml to correspond to your configurationrake pre_commit

and…Make the first test.

Create new folder in your project called spec. Create a file named e.g. basic_test.rb and fill it with

describe "Sum computation" do  
  it "should return 2" do    
    (1+1).should == 2  
  end
end

run it with

spec spec/basic_test.rb

Your test should finish sucessfuly:

.Finished in 0.006001 seconds1 example, 0 failures

Working with rails

That’s great! Now, let’s make it running with your rails objects. Go to the root of your application and install rspec plugins:

ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec
ruby script/plugin install svn://rubyforge.org/var/svn/rspec/tags/CURRENT/rspec_on_rails

bootstrap your application with

ruby script/generate rspec

and start testing with the rails objects. Use rspec generator to create the first test:

ruby script/generate rspec_model user

It generates file spec/models/user_spec.rb file

require File.dirname(__FILE__) + '/../spec_helper'
describe User do  
  before(:each) do    
    @user = User.new  
  end  
 
  it "should be valid" do    
    @user.should be_valid  
  end
end

And now you can just extend the pre-generated file and enjoy it.

Ruby on Rails with Oracle

I am working on a prototype in an big company and they do store data in Oracle. It took me some time to set up RoR working with Oracle. So, here are the things you need to do.

First of all, there is a great tutorial on Oracle site: http://www.oracle.com/technology/pub/articles/haefel-oracle-ruby.html.
In fact, you need to:

Download Ruby OCI library from http://rubyforge.org/projects/ruby-oci8

Configure access to Oracle in database.yml

development:
  adapter: oci
  username: your_username
  password: your_password
  host: HOST_NAME

Create a sequencer for each table (rails uses it to generate id). The sequencer must follow naming convention (see script below). You can create one using:

CREATE SEQUENCE <<table_name>>_seq;

Since I am using one of the non-english character sets and the Oracle instance uses ISO 8859-2 and it is not compatible with Windows code page, I had problems with encoding. To avoid it, it is necessary to set up variable NLS_LANG. I did it in environment.rb.

ENV[’NLS_LANG’]=’czech_CZECH REPUBLIC.UTF8′

Now you should be able to access the data source, perform basic operations with data, and see the data correctly.

How to show performance statistics in a chart

Working on performance tests and tuning is an interesting and challenging job. One has to prepare tests, execute and also evaluate them. The preparation and execution is not always easy, but it is manageable. The evaluation of the tests comes with an interesting problem. The problem is called data visualization.

I was testing a system spread across several servers and there were several technologies involved (Microsoft perfmon, Apache jMeter) in the testing and monitoring. Therefore, the visualization was a challenge.

It is not a problem to put all the statistics into one spreadsheet and try to create a chart. BUT there is usually a lot of tests and the preparation of each chart takes ages. Secondly, the traditional spreadsheets are good to show sales for four regions, but they have problems with hundreds or thousands of data samples. The chart looks like a saw (in MS Excel) or is very CPU intensive (OpenOffice.org). So, automation and a good visualization technique is needed.

I selected gnuplot for the visualization. It is fast, it creates loads of different charts and it is managed from a script console… so, automation is possible. In my approach, the preparation of data files and generation of the gnuplot script is done using ruby scripting language. The resulting chart is nice and its generation took me just a few seconds, including deciding what should be displayed.

Chart

For those with no patience, the script is available for download here.

For the others, here is a short summary of what the script is doing for you. It …

  • Takes several CSV input files as parameters. Thus you can have a chart with data from different servers.
  • Lists all the columns that are in the given CSV file.
  • Gives you the possibility to select the columns of interest.
  • Allows you to specify time format of the timestamp in the file. Default is set to the perfmon format.
  • Scales the data to show all of the data sets in the same chart.
  • Generates a gnuplot script for you. You can then customize the script to your needs.

How it works

0. Create a “temp” directory in the directory where you run the script.

1. Run

ruby process.rb  SERVER3.csv

2. The script then lists all the columns from the CSV file

Select fields (time first, separated by space) from file SERVER3.csv
0 : "(PDH-CSV 4.0) (Central Europe Standard Time)(-60)"
1 : "\\SERVER3\LogicalDisk(C:)\Disk Bytes/sec"
2 : "\\SERVER3\LogicalDisk(D:)\Disk Bytes/sec"
3 : "\\SERVER3\Memory\Available MBytes"
4 : "\\SERVER3\Memory\Page Faults/sec"
5 : "\\SERVER3\Network Interface(HP NC7782 Gigabit Server Adapter)\Bytes Total/sec"
6 : "\\SERVER3\Network Interface(MS TCP Loopback interface)\Bytes Total/sec"
7 : "\\SERVER3\PhysicalDisk(0 C:)\Disk Bytes/sec"
8 : "\\SERVER3\PhysicalDisk(1 D:)\Disk Bytes/sec"
9 : "\\SERVER3\Process(java)\Page Faults/sec"
10 : "\\SERVER3\Processor(0)\% Processor Time"
11 : "\\SERVER3\Processor(1)\% Processor Time"
12 : "\\SERVER3\Processor(2)\% Processor Time"
13 : "\\SERVER3\Processor(3)\% Processor Time"
14 : "\\SERVER3\Processor(4)\% Processor Time"
15 : "\\SERVER3\Processor(5)\% Processor Time"
16 : "\\SERVER3\Processor(6)\% Processor Time"
17 : "\\SERVER3\Processor(7)\% Processor Time"
18 : "\\SERVER3\Processor(_Total)\% Processor Time"
...
36 : "Server monitoring"
Enter your options:

3. Enter the fields you want in the chart. The timestamp field needs to be the first one; fields are separated by spaces.

0 4 9 18

4. Specify the time format. The default is set to perfmon (US English Windows). Press enter, if you want to use the default.

Specify time format. Put HH:mm:SS into round brackets. Default is: DD/MM/YYYY (HH:mm:SS).XXX
DD/MM/YYYY (HH:mm:SS).XXX

5. The script is generated.

gnuplot script created. Generate a picture with the following command
pgnuplot script.plt

6. Edit the script if necessary. If you do not edit the script, you will get a chart like the one above.

set terminal png
set output "chart.png"
set xdata time
set timefmt "%H:%M:%S"
set format x "%H:%M"
set yrange [0:100]
cd "temp"
plot "SERVER3.csv.tmp" using 1:(0.01*$2) with lines title "0.01 * \\\\SERVER3\\Memory\\Page Faults/sec" smooth bezier, \
"SERVER3.csv.tmp" using 1:(0.01*$3) with lines title "0.01 * \\\\SERVER3\\Process(java)\\Page Faults/sec" smooth bezier, \
"SERVER3.csv.tmp" using 1:(1*$4) with lines title "1 * \\\\SERVER3\\Processor(_Total)\\% Processor Time" smooth bezier

7. Generate the chart with the following command

pgnuplot script.plt

8. Check file chart.png

Limitations

  • The script is very simple and definitely will not work for all data files. Nevertheless, for an experienced ruby programmer it should not be a problem to modify it.
  • Hopefully there are not many bugs in there. If you find some, give me a note (comment under this article is appreciated).

I hope you will find the script useful.