Fetching XML in rails (using REXML)

require ‘net/http’
require ‘rexml/document’
url = “http://maps.google.com/maps/api/directions/xml?key=*************************&sensor=false&origin=Chennai&destination=Trichy”
# get the XML data as a string
xml_data = Net::HTTP.get_response(URI.parse(url)).body
# extract event information
doc = REXML::Document.new(xml_data)
duration = []
way = []
kms=[]
full_text=[]
doc.elements.each(‘DirectionsResponse/route/leg/step/html_instructions’) do |a|
way<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/distance/text’) do |a|
kms<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/duration/text’) do |a|
duration<<a.text
end
way.each_with_index do|text, index|
full_text<<“#{kms[index]}(#{duration[index]})—>#{way[index]}<br/>”
end
@full_text=full_text

Google Maps in Rails

The Google Maps API  offers the ability to add mapping functionality, similar to maps.google.com, to their websites. All of Google Maps functionalities, including markers, directions, zoom options and satellite view are only a few lines of code away. To get a Google Maps API key, login to your google account (gmail.com), visit http://code.google.com/apis/maps/signup.html, type the “Website URL” in the box provided (for eg.., localhost:3000, samplesite.com, etc..,) and click on “Generate API key” button. It will take to you to next page and display the API key there. Copy and save it somewhere safely. If you want to get key for both local and server, you need to signup multiple times for “API key”. Now you are ready to code :-

First you need to install couple of plugins for using Google Maps API (YM4R/GM and GEOKIT)

ruby script/plugin install git://github.com/queso/ym4r-gm.git
ruby script/plugin install svn://rubyforge.org/var/svn/geokit/trunk

Consider ‘index’ is the action where you going to display the Google Map in “home controller”.

home_controller.rb

class HomeController < ApplicationController
require ‘rubygems’
include GeoKit::Geocoders
def index
coordinates =[13.0343841,  80.2502535] #you can get the coordinates for the location you want from http://stevemorse.org/jcal/latlon.php
@map = GMap.new(“map”)
@map.control_init(:large_map => true, :map_type => true)
@map.center_zoom_init(coordinates,10) # here 10 referes to the zoom level for a map
@map.overlay_init(GMarker.new(coordinates,:title => “Chennai”, :info_window => “Chennai”))
end
end

/home/index.html.erb

<%= @map.div(:width => 800, :height => 500) %>

That’s it, now run the app. You can see the Google Map pointing out a static location (the location what your coordinates refers too, in this case “Chennai”)

Right, now it’s time perform a dynamic mapping by entering a location in a text box. So for this purpose, add a form in “/home/index.html.erb” at the bottom of the page after <%= @map.div(:width => 800, :height => 500) %>

<% form_for “new_location”, :url => searchmap_path, :html => { :method => :post } do %>
<label>Enter a new Location to map:</label>
<%= text_field_tag :new_location %>
<%= submit_tag “Map It” %>
<% end %>

Now add a routes for searchmap_path in routes.rb

map.searchmap ‘/searchmap’, :controller=>’home’, :action=>’location’

Now, again come back to home_controller.rb, create a method ‘location’

def location
new_location = params[:new_location]
gg = GeoKit::Geocoders::google=”YOUR API KEY GOES HERE”
gg_locate = GeoKit::Geocoders::MultiGeocoder.geocode(new_location)
coordinates = [gg_locate.lat, gg_locate.lng]
@map = GMap.new(“map”)
@map.control_init(:large_map => true, :map_type => true)
@map.center_zoom_init(coordinates,14)
@map.overlay_init(GMarker.new(coordinates, :title => new_location,:info_window =>new_location))
render :action => “index”
end

That’s it. Now you can map to any location you want by entering the address, city or zipcode in the textbox.

Now let’s see how to find the multiple nearby locations (or) how to find the distance between any two locations. For this purpose, add another text_field in the form in “/posts/index.html.erb”

<label>Enter another Location to find distance:</label>
<%= text_field_tag :dist_location %>

Go back to the “home_controller.rb” and add these lines at the bottom before this line(render :action => “index”) in the “location” method  :-

dist_location = params[:dist_location]
#The below part will get execute if you give the second location
if params[:dist_location] && !params[:dist_location].blank?
gg_locate1 = GeoKit::Geocoders::MultiGeocoder.geocode(dist_location)
coordinates1 = [gg_locate1.lat, gg_locate1.lng]
@dist=gg_locate.distance_to(gg_locate1) # will get the distance in miles
@dist=@dist*1.6 #converting it into kms
@map.overlay_init(GMarker.new(coordinates1, :title => “#{dist_location} – #{@dist.round(2)} Kms from #{new_location}”, :info_bubble => “#{@dist} from #{new_location}”))
end

Now, run the app, consider i’m entering “Chennai” as the first location and “Tambaram” as the second location. I will get the below map :-

To get the directions between two locations (by car)

Install the gem google_directions

sudo gem install google_directions

Add these lines in the “home_controller.rb” within the if condition (if params[:dist_location] && !params[:dist_location].blank?) :-

require ‘google_directions’

require ‘net/http’
require ‘rexml/document’

@directions = GoogleDirections.new(new_location, dist_location)
url = “#{@directions.xml_call}”
# get the XML data as a string
xml_data = Net::HTTP.get_response(URI.parse(url)).body
# extract event information
doc = REXML::Document.new(xml_data)
duration = []
way = []
kms=[]
full_text=[]
doc.elements.each(‘DirectionsResponse/route/leg/step/html_instructions’) do |a|
way<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/distance/text’) do |a|
kms<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/duration/text’) do |a|
duration<<a.text
end
way.each_with_index do|text, index|
full_text<<“#{kms[index]}(#{duration[index]})—>#{way[index]}<br/>”
end
@full_text=full_text

Add these lines in the view file at the bottom (‘/home/index.html.erb’)

<% if @full_text %>
<b>
Total Kms : <%= @directions.distance_in_miles*1.6 %><br/>
Total Time Required (minimum) : <%= (@directions.drive_time_in_minutes/60).round %> Hour(s) <%= @directions.drive_time_in_minutes%60 %> Mins<br/>
Directions :- <b/><br/>
<%= @full_text %>
<% end %>

Result of this :-


.

.

.

.

Here is the overall code of “home_controller.rb

require ‘rubygems’
require ‘google_directions’
include GeoKit::Geocoders

def index
coordinates =[13.0343841,  80.2502535] #you can get the coordinates for the location you want from http://stevemorse.org/jcal/latlon.php
@map = GMap.new(“map”)
@map.control_init(:large_map => true, :map_type => true)
@map.center_zoom_init(coordinates,10) # here 10 referes to the zoom level for a map
@map.overlay_init(GMarker.new(coordinates,:title => “Chennai”, :info_window => “Chennai”))
end

def location
new_location = params[:new_location]
dist_location = params[:dist_location]
gg = GeoKit::Geocoders::google=”YOUR API KEY GOES HERE”
gg_locate = GeoKit::Geocoders::MultiGeocoder.geocode(new_location)
coordinates = [gg_locate.lat, gg_locate.lng]
@map = GMap.new(“map”)
@map.control_init(:large_map => true, :map_type => true)
@map.center_zoom_init(coordinates,10)
@map.overlay_init(GMarker.new(coordinates, :title => new_location, :info_window => new_location))

if params[:dist_location] && !params[:dist_location].blank?
gg_locate1 = GeoKit::Geocoders::MultiGeocoder.geocode(dist_location)
coordinates1 = [gg_locate1.lat, gg_locate1.lng]
@dist=gg_locate.distance_to(gg_locate1)
@dist=@dist*1.6
@directions = GoogleDirections.new(new_location, dist_location)
@map.overlay_init(GMarker.new(coordinates1, :title => “#{dist_location} – #{@dist.round(2)} Kms away from #{new_location}”, :info_window => “#{dist_location} – #{@dist.round(2)} Kms <br/> away from #{new_location}”))
require ‘net/http’
require ‘rexml/document’
url = “#{@directions.xml_call}”
# get the XML data as a string
xml_data = Net::HTTP.get_response(URI.parse(url)).body
# extract event information
doc = REXML::Document.new(xml_data)
duration = []
way = []
kms=[]
full_text=[]
doc.elements.each(‘DirectionsResponse/route/leg/step/html_instructions’) do |a|
way<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/distance/text’) do |a|
kms<<a.text
end
doc.elements.each(‘DirectionsResponse/route/leg/step/duration/text’) do |a|
duration<<a.text
end
way.each_with_index do|text, index|
full_text<<“#{kms[index]}(#{duration[index]})—>#{way[index]}<br/>”
end
@full_text=full_text
end
render :action => “index”
end

Here is the overall code of “/home/index.html.erb”

<%= @map.div(:width => 800, :height => 500) %>

<% form_for “new_location”, :url => searchmap_path, :html => { :method => :post } do %>
<label>Enter a new Location to map:</label>
<%= text_field_tag :new_location %>
<label>Enter another Location to find distance:</label>
<%= text_field_tag :dist_location %>
<%= submit_tag “Map It” %>
<% end %>

<% if @full_text %>
<b>
Total Kms : <%= @directions.distance_in_miles*1.6 %><br/>
Total Time Required (minimum) : <%= (@directions.drive_time_in_minutes/60).round %> Hour(s) <%= @directions.drive_time_in_minutes%60 %> Mins<br/>
Directions :- <b/><br/>
<%= @full_text %>
<% end %>

Comparition of Adopting Unobstructive Javascript and XSS in Rails 2 & 3

Cross-Site-Scripting in Rails 2

<%= @post.body %> –> Unsafe
<%= h @post.body %> –> Safe

Cross-Site-Scripting in Rails 3

<%= @post.body %> –> Safe
<%= raw @post.body %> –> Unsafe

Adopting Unobstructive Javascript
Example 1 :

Rails 2:

<%= link_to_remote ‘Show’, :url => post %>

Will generate a HTML like,
“<a href=”#” onclick=”new Ajax.Request(‘/posts/1′, {asynchronous:true,
evalScripts:true, parameters:’authenticity_token=’ +
encodeURIComponent(‘9sk..44d’)}); return false;”>Show</a>”
Rails 3:

<%= link_to ‘Show’, post, :remote => true %>

Will generate a HTML like,
“<a href=”/posts/1″ data-remote=”true”>Show</a>”

Example 2 :

Rails 2:

<% remote_form_for(@post) do |f| %>

Will generate a HTML like,
“<form action=”/posts” id=”new_post” method=”post”
onsubmit=”new Ajax.Request(‘/posts’, {asynchronous:true,
evalScripts:true, parameters:Form.serialize(this)}); return false;”>”
Rails 3:

<% form_for(@post, :remote => true) do |f| %>

Will generate a HTML like,
“<form action=”/posts” data-remote=”true” id=”new_post” method=”post”>”

Example 3 :

Rails 2 & 3:

<%= link_to ‘Destroy’, post, :method => :delete %>

Will generate a HTML like this for Rails 2,
“<a href=”/posts/1″ onclick=”var f = document.createElement(‘form’); f.style.display = ‘none’;
this.parentNode.appendChild(f); f.method = ‘POST’; f.action = this.href;var m =
document.createElement(‘input’); m.setAttribute(‘type’, ‘hidden’); m.setAttribute(‘name’, ‘_method’);
m.setAttribute(‘value’, ‘delete’); f.appendChild(m);var s = document.createElement(‘input’);
s.setAttribute(‘type’, ‘hidden’); s.setAttribute(‘name’, ‘authenticity_token’); s.setAttribute(‘value’,
‘9skdJ0k+l9/q3PWToz6MtfyiB2gcyhnKubeGV6WFL44=’); f.appendChild(s);f.submit();return false;”>Destroy</a>”

And Will generate a HTML like this in Rails 3,
“<a href=”/posts/1″ data-method=”delete” rel=”nofollow”>Destroy</a>”

Example 4 :

Rails 2 & 3:

<%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %>

Will generate a HTML like this for Rails 2,
“<a href=”/posts/1″ onclick=”if (confirm(‘Are you sure?’)) { var f = document.createElement(‘form’);
f.style.display = ‘none’; this.parentNode.appendChild(f); f.method = ‘POST’; f.action = this.href;var m =
document.createElement(‘input’); m.setAttribute(‘type’, ‘hidden’); m.setAttribute(‘name’, ‘_method’);
m.setAttribute(‘value’, ‘delete’); f.appendChild(m);var s = document.createElement(‘input’);
s.setAttribute(‘type’, ‘hidden’); s.setAttribute(‘name’, ‘authenticity_token’); s.setAttribute(‘value’,
‘9skdJ0k+l9/q3PWToz6MtfyiB2gcyhnKubeGV6WFL44=’); f.appendChild(s);f.submit(); };return false;”>Destroy</a>”

And Will generate a HTML like this in Rails 3,
“<a href=”/posts/1″ data-confirm=”Are you sure?” data-method=”delete” rel=”nofollow”>Destroy</a>”

Example 5 :

Rails 2 :

<%= f.submit ‘Create Post’, :disable_with => “Please wait…” %>

Will generate a HTML like ,
“<input id=”post_submit” name=”commit” onclick=”if (window.hiddenCommit)
{ window.hiddenCommit.setAttribute(‘value’, this.value); }else { hiddenCommit =
document.createElement(‘input’);hiddenCommit.type = ‘hidden’;hiddenCommit.value =
this.value;hiddenCommit.name =
this.name;this.form.appendChild(hiddenCommit); }this.setAttribute(‘originalValue’,
this.value);this.disabled = true;this.value=’Please wait…’;result =
(this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) :
this.form.submit());if (result == false) { this.value =
this.getAttribute(‘originalValue’);this.disabled = false; }return result;” type=”submit”
value=”Create Post” />”

Rails 3 :

<%= f.submit :disable_with => “Please wait…” %>

Will generate a HTML like ,

“<input data-disable-with=”Please wait…”
id=”post_submit” name=”commit” type=”submit” value=”Create Post” />”

Difference in ActionMailer between rails 2 and rails 3

Rails 2


def welcome(user)
    @recipients = “#{user.email}”
    @from = “admin@samplesite.com”
    @subject = “Welcome Mail”
    @body[:user] = user
end

Rails 3


def welcome(user)
    @user = user
    mail(:from=>”admin@samplesite.com”, :to=>”#{user.email}”, :subject=>”Welcome Mail”)
end

We can also set the default value if it is common for all the methods. For ex, consider ‘from’ address is common for all the mail notifications. If so, we can set the default ‘from’ address commonly before the methods, in this case no need to set ‘from’ address in each and every method separately.

default :from => “admin@samplesite.com”

DB and Log backup’s using Rake Tasks

Add this in your rakefile for taking log and db backup’s.

require ‘fileutils’
namespace :backup do
  #for taking log backup -start
  desc ‘backup log’
  namespace :log do
   desc ‘rake backup:log:all’
   task :all do
    backup_path = File.join(Rails.root, ‘backup’, ‘log’, “#{Date.today.month}”)
    FileUtils.mkdir_p(backup_path) unless File.exist?(backup_path)
    filename = File.join(backup_path, “log_#{Time.now.strftime(“%Y%m%d”)}.tar.gz”)
    cmd = “tar -czvf #{filename} log/*.log”
    `#{cmd}`
    Rake::Task[“log:clear”].invoke if File.size?(filename)
   end
  end
  #for taking log backup -end

  #for taking db backup -start
  desc ‘backup db’
   namespace :db do
   desc ‘rake backup:db:mysql’
   task :mysql => :environment do
    backup_path = File.join(Rails.root, ‘backup’, ‘db’, “#{Date.today.year}-#{Date.today.month}”)
    FileUtils.mkdir_p(backup_path) unless File.exist?(backup_path)
    tmp_filename = File.join(Rails.root, ‘backup’, ‘db’, ‘tmp.sql’)
    filename = File.join(backup_path, “db_#{Rails.env}_#{Time.now.strftime(“%Y%m%d%H%M%S”)}.tar.gz”)
    db_options = YAML.load_file(File.join(Rails.root, ‘config’, ‘database.yml’))[Rails.env].symbolize_keys
    cmd = <<-CMD
        mysqldump  GetProject_development -u root -proot  > #{tmp_filename}
tar -czvf #{filename} backup/db/tmp.sql

    CMD
    `#{cmd}`
   end
  end
#for taking db backup -end
end

That’s it now run

rake backup:log:all

to take a backup of log (you can also run this rake daily once automatically for taking daily backups). This will take a backup of log, and clear the current log file’s contents. Similarly, for taking db backup run

rake backup:db:mysql

All the backups will be stored in a folder named “backup” which will be available at the root path of the app.

HAML

Haml is a markup language used to describe XHTML. Haml is very easy to read and enables developers to avoid explicitly coding XHTML into their templates. Haml was originally written by Hampton Catlin. Haml also includes a counterpart, Sass, for creating CSS. The official implementation of Haml has been built for Ruby with plugins for Ruby on Rails.

Haml is a templating engine for HTML. It’s are designed to make it both easier and more pleasant to write HTML documents, by eliminating redundancy, reflecting the underlying structure that the document represents, and providing elegant, easily understandable, and powerful syntax.

The first step is to install the gem:

gem install haml

Syntax for HAML

The most basic element of Haml is a shorthand for creating HTML:

%tagname(attr1=’value1′ attr2=’value2′) Contents

Adding class and id attributes is even easier. Haml uses the same syntax as the CSS that styles the document:

%tagname#id.class

In fact, when you’re using the <div> tag, it becomes even easier. Because <div> is such a common element, a tag without a name defaults to a div.

#foo Hello!

You can also put plain text as a child of an element:

%p

Hello,

World!

Example HAML

The first step to creating a view inside a Rails application using Haml is to replace .html.erb with .haml. For example, the view corresponding to the show action in a employee controller would be RAILS_ROOT/app/views/employee/show.haml

Haml is simple to use. To reproduce a XHTML tag, simply use %tag. Closing tags is not required and handled via indentation. Indentation must be 2 spaces.

#main

.note

%h2 RoR Blog

%ul

%li

Haml is indented with

%strong two spaces *only*

Which will be automatically converted to,

<div id=’main’>

<div class=’note’>

<h2>RoR Blog</h2>

<ul>

<li>

Haml is indented with

<strong>two spaces *only*</strong>

</li>

</ul>

</div>

</div>

Example 2

!!!

%html{ : xmlns => “http://www.w3.org/1999/xhtml&#8221;, :lang => “en”, “xml:lang” => “en”}

%head

%title BoBlog

%meta{“http-equiv” => “Content-Type”, :content => “text/html; charset=utf-8”}

%link{“rel” => “stylesheet”, “href” => “main.css”, “type” => “text/css”}

%body

#header

%h1 BoBlog

%h2 Bob’s Blog

#content

– @entries.each do |entry|

.entry

%h3.title= entry.title

%p.date= entry.posted.strftime(“%A, %B %d, %Y”)

%p.body= entry.body

#footer

%p

© Selva

Will generate,

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<html lang=’en’ xml:lang=’en’ xmlns=’http://www.w3.org/1999/xhtml’&gt;

<head>

<title>BoBlog</title>

<meta content=’text/html; charset=utf-8′ http-equiv=’Content-Type’ />

<link href=”/stylesheets/main.css” media=”screen” rel=”Stylesheet” type=”text/css” />

</head>

<body>

<div id=’header’>

<h1>BoBlog</h1>

<h2>Bob’s Blog</h2>

</div>

<div id=’content’>

<div class=’entry’>

<h3 class=’title’>Halloween</h3>

<p class=’date’>Tuesday, October 31, 2006</p>

<p class=’body’>

Happy Halloween, glorious readers! I’m going to a party this evening… I’m very excited.

</p>

</div>

<div class=’entry’>

<h3 class=’title’>New Rails Templating Engine</h3>

<p class=’date’>Friday, August 11, 2006</p>

<p class=’body’>

There’s a very cool new Templating Engine out for Ruby on Rails. It’s called Haml.

</p>

</div>

</div>

<div id=’footer’>

<p>

© Selva

</p>

</div>

</body>

</html>