Wednesday, August 31, 2011

Generate CSV file using FasterCSV

Generate csv file using different tools like FasterCSV or CSV builder.

FasterCSV is better tool to generate csv file using ruby.
First of all need to install gem using gem install fastercsv.

Create .csv file by following below steps.
 
require 'fastercsv'

file_path = Tempfile.new(
"test.csv", File.join(Rails.root,"tmp"))
FasterCSV.open(file_path.path, "w:windows-1252") do |content|
  content << ["Name", "Surname", "Birthdate", "HSC Percentage", "URL"]
  content << ["Priyanka", "Pathak", Date.parse("May 20, 1986"), 80, '=HYPERLINK("http://priyankapathak.wordpress.com","Get me here")']
end

This will simply generate test.csv file with your required format like hyperlink in csv.

Hope this post will help you.

Friday, August 26, 2011

Inbulit ruby on rails test method

Hello rubies,
      One of best feature which rails provides is inbuilt testing. I like to write the test case to trace behavior of application.
      Below the list of the method which you use during functional and integration tests.

Functional Test

  1. HTML request
      a. Get method
          get :action_name, :parent_params => {:child1 => "arg1"}
      b. Post method
          post :action_name, :parent_params => {:child1 => "arg1", :child2 => "arg2"}

  2. Ajax request
      a. Post method
          xhr :post, :action_name, , :parent_params => {:child1 => "arg1"}


Integration Test

  If you want to pass additional header than use  
  headers = {'HTTP_HOST' => "localhost", 'Content-Type' => 'text/xml'}

  1. HTML request
      a. Get method
          get_via_redirect '/controller_name/action_name', {:arg1 => 'test'}
      b. Post method 
          post_via_redirect '/controller_name/action_name', {:arg1 => 'test'}, headers
      c. Put method
        
          put_via_redirect '/controller_name/action_name', {:arg1 => 'test'}
      d. Delete method
          delete_via_redirect '/controller_name/action_name', {:arg1 => 'test'}
      f. Instead of method*_via_redirect you can use alternate method
        http_method like post, put, get, delete        
        request_via_redirect http_method, '/controller_name/action_name', {:arg1 => 'test'}
    
  2. Ajax request
      a. Post method
          xml_http_request :post, "/controller_name/action_name", {:arg1 => 'test'}, headers

This are the basic methods. If you need detail information on this then refer

http://guides.rubyonrails.org/testing.html

Thursday, August 25, 2011

Patch to allow link_to with post method

Hello guys,
     If you want to pass additional parameters with post method in link_to than you have to add patch in url_helper of actionpack module of rails.

Here is the simple patch to allow post method with additional parameters in link_to.

Go to the actionpack folder of rails for eg we have rails 2.3.11.

nano /usr/lib/ruby/gems/1.8/gems/actionpack-2.3.11/lib/action_view/helpers/url_helper.rb

Now just replace below lines

line #562
method, href = html_options.delete("method"), html_options['href']
to 
method, href, values = html_options.delete("method"), html_options['href'], html_options.delete("values")
line #570
"if (#{confirm_javascript_function(confirm)}) 
{ #{method_javascript_function(method, url, href)} };return false;"
to
"if (#{confirm_javascript_function(confirm)}) 
{ #{method_javascript_function(method, values, url, href)} };return false;"

line #574 
"#{method_javascript_function(method, url, href)}return false;"
to
"#{method_javascript_function(method, values, url, href)}return false;"

line #590
def method_javascript_function(method, url = '', href = nil)
to
def method_javascript_function(method, values, url = '', href = nil)

and add below code after line #595
 
  if values.is_a?(Hash) && (method == :post || method == :put) 
    values.each do |name,value| 
      submit_function << "var formElement = document.createElement('input'); " 
      submit_function << "formElement.name = '#{name}'; " 
      submit_function << "formElement.type = 'text'; " 
      submit_function << "formElement.value = '#{value}'; " 
      submit_function << "f.appendChild(formElement); " 
    end 
  end 

Finally now you can access the link_to with post action and query parameters.
<%= link_to "Test to click on",
  {:controller => "users", :action => "dummy_action"}, :method => :post, 
   :values => {:arg1 => "Argument1", :arg2 => "Argument 2"}, 
   :class => 'css_class' %>

Hope this post helps you to overcome the problem of link_to during post method.
If you have any suggestion then post comment. 

Friday, August 19, 2011

Faster XML Parser in ruby on rails

Hello Guys,

Last week i was trying to  parse xml using different xml parser like Hpricot. But when we have large amount of data than segment fault occurs. So i moved to better and faster xml parser called libxml-ruby.

There is simple steps to parse large xml using libxml-ruby. First of all you need to install libxml-ruby by

  gem install libxml-ruby

Lets, we have sample xml

sample.xml
xml = %{
  <users>
    <user>
      <name>Priyanka Pathak</name>
      <mark subject=”biology”> 80 </mark>
    </user>
    <user>
      <name>Rahul Pathak</name>
      <mark subject=”biology”> 85 </mark>
    </user>
  </users>
}

Now create method to parse xml

require 'rubygems'
require 'libxml'
require 'benchmark'

def parse_xml
   Benchmark.bmbm do |r|
      r.report("Process XML"){
        parser = LibXML::XML::Parser.file('sample.xml',:encoding => XML::Encoding::UTF_8)
        doc, collect_data = parser.parse, []
        doc.find('//users/user').each do |e|
           data = {}
           data['name'] = e.find('name').first.content
           mark = e.find('mark').first
           data['mark'] = {:subject => mark.attributes.first.value , :value => mark.content}
           collect_data << data     
        end

        puts "collect data: " + collect_data.inspect
     }
   end
end
Benchmark shows the time required during xml parsing and as per my experience it's faster than other xml parser.

For more information about libxml follow http://libxml.rubyforge.org/rdoc/
Hope this post will help you.

Thursday, August 18, 2011

Validate XSD with XML

If you want to validate the XSD (XML schema) with XML document then here is the easy steps.



First you need to install libxml-ruby via gem install command.



We have 2 files. one is example.xsd and example.xml. Lets we define normal method say validate_xml_schema.

require 'libxml'
def validate_xml_schema
   begin
      schema = XML::Schema.document(XML::Document.file("#{RAILS_ROOT}/example.xsd"))
      xml_instance = XML::Document.file("#{RAILS_ROOT}/example.xml")                  
      if xml_instance.validate_schema(schema)
         puts "Successfully validate schema"
      else
         puts "Oops!! There is some problem in XML formatting"
      end     
   rescue => e
     puts "Exception:" + e.inspect
   end 
end

Here is the two example documents.

example.xml

<?xml version="1.0" encoding="UTF-8"?>
<students>
   <student>
      <roll_no>1001</roll_no>
      <name>Priyanka Pathak</name>
      <mark subject='biology'>48</mark>
      <mark subject='physics'>42</mark>
   </student>
   <student>
      <roll_no>1002</roll_no>
      <name>Rahul Pathak</name>
      <mark subject='biology'>45</mark>     
      <mark subject='physics'>43</mark>
   </student>
</students>


example.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="students">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="student"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="student">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="roll_no"/>
        <xs:element ref="name"/>
        <xs:element minOccurs="1" maxOccurs="2" ref="mark"/>    
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="roll_no" type="xs:integer"/>

  <xs:element name="name" type="xs:string"/>

  <xs:element name="mark">
    <xs:complexType>
      <xs:simpleContent>
          <xs:extension base="xs:integer">
            <xs:attribute name="subject" use="required">
              <xs:simpleType>
                <xs:restriction base="xs:string">          
                  <xs:enumeration value="biology"/>
                  <xs:enumeration value="physics"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
          </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>


XSD schema defines structure of nodes and value type.
eg. roll_no must be positive integer.
      name must be string.
      mark must contain subject as attribute with option like 'biology' or 'physics' and value type as decimal.

Hope this post helps you.

Run rake task in background

Hey rubies,
                Some time we need immediate response at that time we have option to run functionality in background by invoking rake task.

Here is the small example

Assume we have task called 'generate_random_number' which we need to invoke in background. below is the steps for that.

Invoke the background task by

call_rake 'generate_random_number', {:initial => 10}

definition for call_rake

def call_rake(task, options = {})   
    # define rails environment as option etc...
    options[:rails_env] ||= RAILS_ENV
    # collect argument list
    args = options.map { |n, v| "#{n.to_s.upcase}='#{v}'" }         
    # invoke task from rails and generate log
    system "rake #{task} #{args.join(' ')} --trace 2>&1 >> #{RAILS_ROOT}/rake.log &"   
  end

Here is the task definition.
desc "Generate Random Number"
task :generate_random_number, [:initial] => :environment do |t, args|
    puts "here is your random number " + rand(args[:initial] ).to_s
end

This the way how task execute in background. If you have any query or suggestion then post the comment.

Wednesday, August 17, 2011

Get sub classes and super class in ruby on rails

Get the sub classes from super class by using command

subclasses_of(Parent Class Name)

Get the super class from sub class by using command

Child Class Name.superclass

eg. Class User
      end

     Class Admin < User
     end
    
     Class Employee < User
     end

Lets we have User as super class and which inherited by sub classes Admin and Employee respectively.

If we need to get child classes by using subclasses_of(User) and to get parent class by using Admin.superclass.