Thursday, October 30, 2008

Make Activemessaging Working on Rails 2.1.0

Few days ago we had updated the application on which project currently I am working to make it compatible with rails 2.1.0. Previously we were using rails 1.2.5. In our application we have mail sending module for which we are using activemessaging plugin. It was working fine on previous version. But, unfortunately on new version it was not working. We thought that we made some mistake while updating to the new version. The problem was the poller was not starting and it was showing the following message when we were trying to run the poller-

Dispatch exception: undefined method `prepare_application' for #Dispatcher:0xb6d9ffec>
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/support.rb:8:in `prepare_application_for_dispatch'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:189:in `prepare_application'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:199:in `dispatch'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:197:in `synchronize'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:197:in `dispatch'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:93:in `stop'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:90:in `start'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:90:in `stop'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:80:in `each'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:80:in `stop'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging/gateway.rb:67:in `start'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/lib/activemessaging.rb:108:in `start'
/mnt/app/releases/20081017130017/vendor/plugins/activemessaging/poller.rb:14
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/application.rb:176:in `load'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/application.rb:176:in `start_load'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/application.rb:253:in `start'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/controller.rb:72:in `run'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons.rb:139:in `run'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/cmdline.rb:105:in `call'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons/cmdline.rb:105:in `catch_exceptions'
/var/lib/gems/1.8/gems/daemons-1.0.10/lib/daemons.rb:138:in `run'
script/poller:21


After googling I found that the plugin has a problem to work with rails 2.1.0. http://groups.google.com/group/activemessaging-discuss/browse_thread/thread/41989b6599146ba4- - in this site you will find the details. After replacing the content of vendor/activemessaginglib/activemessaging/support.rb with the following code the poller was working fine -

require 'dispatcher' unless defined?(::Dispatcher)
::Dispatcher.class_eval do
def self.prepare_application_for_dispatch
new(STDOUT).reload_application
end

def self.reset_application_after_dispatch
new(STDOUT).cleanup_application
end
end

It is really bad if someone needs to do such things to make the plugins working while updating any project to any newer rails version.

Tuesday, September 30, 2008

Reading attributes value of an Xml node

It is common to read the attribute of an xml node while trying to read xml files. Lets we have an xml like below -


We can write the following code to read the value of the attribute “id” of the first customer –

// Load the xml file
XmlDocument doc = new XmlDocument();
doc.LoadXml(Resources.XMLFile);

// Read the first customer element
XmlNode customer = doc.DocumentElement.SelectSingleNode("customer");

// Initialize the reader using the customer node
// from where need to read attributes
XmlNodeReader reader = new XmlNodeReader(customer);
reader.Read();

// Read the attribute named - "id"
string id = reader.GetAttribute("id");
Console.WriteLine(id);

The output of this program is "123". I find it helpful during working one of my project and I think it will also help you. You can also read this value very easily if you use LINQ in C# 3.0.

Saturday, July 12, 2008

Exporting and Importing to CSV File in Rails

CSV file format is very popular when we want to give option to export or import tabular data in our application. Rails has a very good support to do this. In this post I will discuss both exporting and importing to CSV file in Rails application.

For our export and import purpose, we will use a table named USERS which is like below:


Import From CSV:

Import information from any comma separated CSV file is so simple in Rails. Here, we want to import user information to insert users in our USERS table and the information into CSV file is like below:



To import this we need a view from where we can submit our CSV file through a multipart form. Here is a simple form view:


<% form_tag url_for(:controller => "export_import", :action => "import_user_from_csv"), {:multipart => true} do -%>

<%= file_field_tag :csv_file -%>

<%= submit_tag 'Import' -%>

<% end -%>


After submitting this form it will goes to the specified action(in our case it will goes to controller: “ExportImportController” and action: “import_user_from_csv” ) from where we will actually import the necessary information from the file uploaded. The code of the action is like below:


require "csv"
class ExportImportController < style="font-style: italic;">
def index

end

def import_user_from_csv
# parse the csv file using ruby "csv"-librarty
parsed_file = CSV::Reader.parse(params[:csv_file])

# print all rows of the csv file into the log file
parsed_file.each do |row|
logger.info "Information From CSV >> Id : #{row[0].inspect} Name: #{row[1].inspect} Email: #{row[2].inspect}"
end


redirect_to :action => :index
end
end


Here one important thing is that, we are using require "csv" which library provides us option to parse csv file.

I am not showing how to insert this information into Database. Because, once we have all information on our hand, we can play with it in any way we want. I am just giving an idea. Place the following code into the loop(parsed_file.each do |row|):


if(User.exists?(row[0]))
User.update(row[0], {:name => row[1], :email => row[2]})
else
User.create(:name => row[1], :email => row[2])
end


Above line will insert information into USERS table. But, we can not use it directly in our application as we need to handle all kind of exceptions.


Export to CSV:

There is a FasterCSV ruby library which provides easy way to export our information to CSV file. To use it you can install gems using “gem install fastercsv” or download it from http://fastercsv.rubyforge.org/ and extract it to RAILS_HOME/vendor/plugins/fastercsv.


Suppose we want to export all users of USERS table to CSV file. FasterCSV provides a output stream in which we can insert arrays as rows(one array one row) to CSV file using “<<”. Once we have the streaming data we can send it to the browser.


Following code can be used to export all users to "users.csv":


class ExportImportController < ApplicationController
def export_users
# get all users from user table
users = User.find(:all)

# generate the streaming data
csv_string = FasterCSV.generate do |csv|
csv << ["Id", "Name", "Email Address"]
users.each do |user|
csv << [user.id, user.name, user.email] end
end

# send csv file(users.csv) to browser
send_data(csv_string, :type => 'text/csv; charset=utf-8; header=present', :filename => "users.csv")
end
end