Monday, May 25, 2009

Integrate Google map API with Ruby on Rails application

In this tutorial I create an application using Google map API. I develop a map for a city and user can insert there location to the map and they can view those places by clicking the icon. When adding location they can add a photo of the location as well. This is very simple application and can develop it further more as you wish. For upload images I use attachment_fu plug-in and it can easily use for file upload purposes.

First create a rails application called Map.You can create application through Netbeans or in command line (windows). I am using the command line for creating the application.

C:\> rails Map

Now create the database called map_development. You can use postgres or mysql for create the database. I am using postgres for create the database. According to your database you have to edit the database.yml file. If its mysql replace the adapter “postgresql” to “mysql” give the database name, user name and password.

Development:
adapter: postgresql
database: map_development
username: postgres
password:
host: localhost

Then go to map folder and Run the rails application.

C:\> cd Map
C:\Map>ruby script/sever
Go to web browser type http://localhost:3000/ . If database is correct it should show the application’s environment without error.

Let install the Rick Olson's attachment_fu plug-in to the map application. You can get more information about the plugin using following link http://clarkware.com/cgi/blosxom/2007/02/24. This plug in require rails 1.2 or above rails version.


C:\Map> ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/

Now we create a two model for map application. One is used with attachement_fu plug-in. This will store the uploaded information of the image file. Other model is use to store the location that insert by the user. First generate the image model for upload images.

C:\Map>ruby script/generate model image

Go to db/migrate/20090619033949_create_images.rb file insert the following code.

class CreateImages < ActiveRecord::Migration
def self.up
create_table :images do |t|
t.column "location_id", :integer
t.column "filename", :string, :limit => 255
t.column "path", :string, :limit => 255
t.column "content_type", :string
t.column "size", :integer
t.column "width", :integer
t.column "height", :integer
t.column "parent_id", :integer
t.column "thumbnail", :string
t.column "created_at", :datetime
t.timestamps
end
end

def self.down
drop_table :images
end

end

Let us create another model called location to store the user entered places. The fields are name, longitude, latitude and description. Longitude and the latitude is use for show the location in the map.

C:\Map>ruby script/generate model location

Go to db/migrate/20090619035403_create_locations.rb file and insert the following lines.

class CreateLocations < activerecord::migration
def self.up
create_table :locations do |t|
t.column "name", :string, :limit => 100
t.column "description", :string
t.column "longitude", :decimal
t.column "latitude", :decimal
t.timestamps
end
end

def self.down
drop_table :locations
end
end

Now you have created the required migration files, its time to execute them against the database. To do this, go to a command prompt and go to the library directory, in which the application is located, and then type rake migrate.

C:\Map>rake db:migrate

This will create images and locations tables in map_development database. Now go to database and check the two tables.

When uploading the images we have to validate those image for weather its file type and file size. Also we can resize the image when uploading. For this function you have to install one of the gem from following gems ImageScience, RMagick or minimagick. Otherwise this resizing function will not work.

Go to \app\models\image.rb and write following code.

class Image < activerecord::base
has_attachment :content_type => :image,
:storage => :file_system,
:min_size => 0,
:max_size => 1.megabytes,
:resize_to => '320x240',
:thumbnails => { :medium => '150x150'}

#Override the default AttachmentFu error messages.
def validate
if filename.nil?
#errors.add_to_base("You must choose a file to upload")
else
# Images should only be GIF, JPEG, or PNG
enum = attachment_options[:content_type]
unless enum.nil? || enum.include?(send(:content_type))
errors.add_to_base("You can only upload images (GIF, JPEG, or PNG)")
end
# Images should be less than UPLOAD_LIMIT MB.
enum = attachment_options[:size]
unless enum.nil? || enum.include?(send(:size))
msg = "Images should be smaller than 1 MB"
errors.add_to_base(msg)
end
end
end
end

We finished the model part. Now we create the controller part next.


To be Continue.....

Friday, April 24, 2009

Create interactive graph in ruby on rails

I am using the chart director 3rd party library to implement the graph. It is a well developed chart tool and gives nice attractive graph. In the internship I used chart director to implement graph in ruby on rails. Ruby has there own graph library but it not attractive therefore not suitable for commercial application.
First you have to download the chart director trial version from http://www.advsofteng.com/download.html and you can develop graph. If you satisfied you can buy a license. Install the chart director to your system. For install you can follow the read me file and install it.

In our application we are creating a graph for student and there particle one subject mark. Its bar chart and x-axis will be student name and y-axis will be marks. It is a very simple graph. To extract data we use a table called marks which include student marks and name.

Create a rails application called Graph.
You can create application through Netbeans or in command line (windows).

C:\> rails Graph

Then you have to create the database(ex:- graph_development). Then you have to edit the database.yml file in config directory. Her I am using postgres as the database. You can use mysql then “adapter: mysql” and you shoud give the username and the password in mysql database.

Development:
adapter: postgresql
database: graph_development
username: postgres
password:
host: localhost

Then go to graph folder and Run the rails application.

C:\> cd Graph
C:\Graph>ruby script/sever

Go to web browser type http://localhost:3000/ . If database is correct it should show the application’s environment without error.




Now, let’s generate the model.

C:\Graph>ruby script/generate model mark

Go to db/migrate/ and open the 20090424083035_create_marks.rb file.


class CreateMarks <>create_table :marks do |t|
t.string :name, :limit => 100, :null => false
t.string :subject_name
t.integer :scored_mark
t.timestamp :created_at
end
end

def self.down
drop_table :marks
end
end


Now you have created the required migration file, its time to execute them against the database. To do this, go to a command prompt and go to the library directory, in which the application is located, and then type rake migrate.

C:\Graph>rake db:migrate

This will create marks tables in graph_development database. Now we insert test data to newly created mark table. We use another migration for insert data.

C:\Graph>ruby script/generate migration addMarks

Then insert data to 20090424085518_addmark migration files as followes.

class Addmark <>Mark.create :name => "David", :subject_name => "Science", :scored_mark => "73"
Mark.create :name => "Smith", :subject_name => "Science", :scored_mark => "86"
Mark.create :name => "Hayden", :subject_name => "Science", :scored_mark => "54"
Mark.create :name => "Warne", :subject_name => "Science", :scored_mark => "28"
Mark.create :name => "Shane", :subject_name => "Science", :scored_mark => "67"
Mark.create :name => "Watson", :subject_name => "Science", :scored_mark => "62"
Mark.create :name => "Taylor", :subject_name => "Science", :scored_mark => "89"
Mark.create :name => "Gilcrist", :subject_name => "Science", :scored_mark => "93"
end

def self.down
end

en
d

Now we again run the rake command. Now the data will be inserted to the mark table and you can check by going to the table. Is it amazing!!! Ruby migration has lot of power. It is the best way to handle schema in database.

C:\Graph>rake db:migrate

Now database creating part and model part is completed. Let us write the controller and view part of our graph application.

Next we will create a controller called graph. It includes the graph code and the business logic.
C:\Graph>ruby script/generate controller graph

This command will create graph controller, helper and folder in view called graph.Then open the graph_controller.rb file. Insert the following cord. I comment all the code and you can experiment by changing value and will change the look and feel of the graph.

require("chartdirector")
class GraphController < style="color: rgb(0, 102, 0);">
# get the marks table data
@marks = Mark.find(:all,:conditions =>["subject_name =?","Science"])

#define array
data = Array.new
labels = Array.new
counter=0


#check @marks array data.
#If nil object pass it gives array therefore we validate it.

if !@marks.nil? then

#feed the data to array
for marks in @marks

# The data for the bar chart
data[counter] = marks.scored_mark.to_i
# The labels for the bar chart
labels[counter] = marks.name
counter = counter + 1


end

end

# Create a XYChart object of size 600 x 370 pixels
c = ChartDirector::XYChart.new(600, 370)

# Add a title to the chart using 18pts Times Bold Italic font
c.addTitle("Students Marks for science subject", "timesbi.ttf", 18)

# Set the plotarea at (60, 40) and of size 500 x 280 pixels. Use a vertical gradient
# color from light blue (eeeeff) to deep blue (0000cc) as background. Set border
and
# grid lines to white (ffffff).
c.setPlotArea(60, 40, 500, 280, c.linearGradientColor(60, 40, 60, 280, 0xeeeeff,
0x0000cc), -1, 0xffffff, 0xffffff)


# Add a multi-color bar chart layer using the supplied data. Use soft lighting effect
# with light direction from left.

c.addBarLayer3(data).setBorderColor(ChartDirector::Transparent,
ChartDirector::softLighting(ChartDirector::Left))


# Set x axis labels using the given labels
c.xAxis().setLabels(labels)

# Draw the ticks between label positions (instead of at label positions)
c.xAxis().setTickOffset(0.5)

# Add a title to the x and y axis with 10pts Arial Bold font
c.yAxis().setTitle("Scored Marks", "arialbd.ttf", 10)
c.xAxis().setTitle("Student name", "arialbd.ttf", 10)


# Set axis label style to 8pts Arial Bold
c.xAxis().setLabelStyle("arialbd.ttf", 8)
c.yAxis().setLabelStyle("arialbd.ttf", 8)

# Set axis line width to 2 pixels
c.xAxis().setWidth(2)
c.yAxis().setWidth(2)


# output the chart
session["chart1"] = c.makeChart2(ChartDirector::PNG)

#puts session["chart1"]
@imageMap = c.getHTMLImageMap("", "","title='{xLabel}: Marks {value}'")

end
end


After that we have to create index.rhtml and new_graph.rhtml. The code should as follows.

index.rhtml

<. iframe width="700px" height="700px" frameborder="0" name="graph" id="graph" scrolling="auto" src="/graph/new_graph">

new_graph.rhtml

<. img src="http://www.blogger.com/post-edit.do" action="" /> 'get_session_data', :id => 'chart1',
:nocache => rand) %>" border="0" usemap="#map1">
<. map name="map1">
<%= @imageMap %>

After that you can run your graph in web browser and it will give 500 server error if you use rails newer version(>2). Don’t get upset you have to do little change in environment.rb. Have to change the session type in to PStore. Now it will work fine.

config.action_controller.session_store = :PStore

Here is our interactive graph. When the mouse pointer go over an it will show the value of bar.




I have spent two days for find the solution for 500 server error. I think it will be useful for other. In chart director normal graph work fine but when it comes to interactive graph gave the error because it saves the graph in session variable. In the rails 2.0 and above version default session has limited for security reason. So it doesn’t give to store the graph in the session. Therefore we have to change the session type. Rails have five session type. In here we use PStore session type for display the interactive graph.











Thursday, April 16, 2009

Introduction

I was working as ruby on rails web developer for 6 month of my internship period. So i though to share my ruby on rails experience with this blog. When the internship period i had a lot of problems in ruby on rails. So i like to share these problems and my solution with you.