Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Thursday, November 5, 2015

Upload Image using CKeditor - Rails

Hello Guys,

   Today i've configure CKeditor (https://github.com/galetahub/ckeditor) to my Rails application and i found there is no upload button along with Image insert dialog.
So i've modified the ckeditor/config.js to below and it then show new tab called 'Upload' in Image insert dialog.

See. config.js

CKEDITOR.editorConfig = function (config) {

  // ... other configuration ...
  config.language = 'en';
  config.toolbar_regular = [
    { name: 'document', items: ['Source'] },
    { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
    { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
    '/',
    { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
    { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
    { name: 'insert', items: ['Table', 'Image', 'HorizontalRule', 'SpecialChar' ] },
    '/',
    { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
    { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
    { name: 'tools', items: [ 'Maximize'] },
    { name: 'plugins', items: ['CodeSnippet', 'Cite'] }
  ];
  config.toolbar_lite = config.toolbar_regular.concat({ name: "lite", items: ["lite_ToggleShow", "lite_AcceptAll", "lite_RejectAll"] });
    config.toolbar = 'regular';
  config.allowedContent = true;
   /* Filebrowser routes */
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed.
  config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
  config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
  // The location of a script that handles file uploads in the Flash dialog.
  config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
  config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
  config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
  // The location of a script that handles file uploads in the Image dialog.
  config.filebrowserImageUploadUrl = "/ckeditor/pictures";
  // The location of a script that handles file uploads.
  config.filebrowserUploadUrl = "/ckeditor/attachment_files";
  // Rails CSRF token
  config.filebrowserParams = function(){
    var csrf_token, csrf_param, meta,
        metas = document.getElementsByTagName('meta'),
        params = new Object();
    for ( var i = 0 ; i < metas.length ; i++ ){
      meta = metas[i];
      switch(meta.name) {
        case "csrf-token":
          csrf_token = meta.content;
          break;
        case "csrf-param":
          csrf_param = meta.content;
          break;
        default:
          continue;
      }
    }
    if (csrf_param !== undefined && csrf_token !== undefined) {
      params[csrf_param] = csrf_token;
    }
    return params;
  };
  config.addQueryString = function( url, params ){
    var queryString = [];
    if ( !params ) {
      return url;
    } else {
      for ( var i in params )
        queryString.push( i + "=" + encodeURIComponent( params[ i ] ) );
    }
    return url + ( ( url.indexOf( "?" ) != -1 ) ? "&" : "?" ) + queryString.join( "&" );
  };
  // Integrate Rails CSRF token into file upload dialogs (link, image, attachment and flash)
  CKEDITOR.on( 'dialogDefinition', function( ev ){
    // Take the dialog name and its definition from the event data.
    var dialogName = ev.data.name;
    var dialogDefinition = ev.data.definition;
    var content, upload;
    if (CKEDITOR.tools.indexOf(['link', 'image', 'attachment', 'flash'], dialogName) > -1) {
      content = (dialogDefinition.getContents('Upload') || dialogDefinition.getContents('upload'));
      upload = (content == null ? null : content.get('upload'));
      if (upload && upload.filebrowser && upload.filebrowser['params'] === undefined) {
        upload.filebrowser['params'] = config.filebrowserParams();
        upload.action = config.addQueryString(upload.action, upload.filebrowser['params']);
      }
    }
  });
};

Hope this article helps you.

Thursday, February 7, 2013

Rebuild the corrupted legacy data.


Hello Guys,
        Yesterday i phase one problem regarding positioning with legacy database. For my rails application i have used the awesome_nested_set to manage nesting/threading. Case is to rearrange the position and for that i have used pretty nice method called 'rebuild!'.

Assume i have model called 'Post' and have nesting per Category .

# id: integer
# category_id: integer
# lft :integer
# parent_id :integer
# position :integer
# rgt :integer
class Post < ActiveRecord::Base
  acts_as_nested_set :scope => :category
end

In the legacy database, having 3 categories called 'Alpha', 'Beta', 'Gama'. In which category Alpha's data mess out.
To over come this problem invoke command on console.
> script/console
> category = Category.find_by_name('Alpha')
> category.posts.rebuild!

Now cross check the data and it results as per need. Hope this post is helpful to you guys. Cheers!!

Monday, July 23, 2012

Generate Rss feed with rails application

  Hey guys,
      Lets today we create the rss feed with our existing rails application. Consider we have controller called post and have index method to show all the available posts. Now meanwhile we need to create feed for available posts as well.

controller:

def index
  @posts = Post.find(:all, :order => "created_at desc")
  respond_to do |format|
     format.html { render :template => 'posts/index.rhtml' }
     format.xml { render :template => 'posts/index.rxml', :layout => false
        headers["Content-Type"] = "application/rss+xml"
     }
  end
end

view:

index.rxml

xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
  xml.channel do
    xml.title 'Available Posts'
    xml.description h("Here is the posts ... blah blah")
   
    @posts.each do |post|
      xml.item do
        xml.title post.title
        xml.link url_for(:only_path => false,
          :controller => 'posts',
          :action => 'show',
          :fishery => post.id)
        xml.description post.description
        xml.pubDate CGI.rfc1123_date(post.created_at)
      end
    end
  end
end

index.rhtml

# Add auto discovery tag to access rss feed

<%= auto_discovery_link_tag :rss, {:controller => "posts", :action => "index"}%>

See your rss feed for posts is ready!! Whenever auto discovery tag found it enables the rss icon on browser. Keep in mind Either you have to use predefined xml node or need to create XSL template. You can also emend the stylesheet into XSL template.

Thursday, July 19, 2012

Get the Date difference in days

Hello guys,
        Wanna to get the date difference in terms of days?

eg.
date_x = Time.now.to_date
date_y = Date.parse('2012-05-20')

passed_days = (date_x.to_date - date_y.to_date).to_i

passed_days should give the date difference in days.

Wednesday, June 20, 2012

Ajax request via javascript

Hello Rubies,
      Have you tried AJAX request via javascript? Lets see the eg.

<script type="text/javascript">

  // Ajax without update parameter:
  function ajax_request(id){
    window._token = '<%= form_authenticity_token %>';
    var url = '/controller/action';
    var pars = 'id=' + id + '&authenticity_token=' + window._token;
    var myAjax = new Ajax.Request(url, {method: 'post', parameters: pars, onFailure: showFailure(), onSuccess: showSuccess() });
  }

  // Ajax with update parameter:
  function ajax_update_request(id){
    window._token = '<%= form_authenticity_token %>';
    var url = '/controller/action';
    var pars = 'id=' + id + '&authenticity_token=' + window._token;
    var myAjax = new Ajax.Updater('update_div_id', url, {method: 'get', parameters: pars, onFailure: showFailure(), onSuccess: showSuccess()});
  }

  function showSuccess(){
  }

  function showFailure(){
  }

</script>

Friday, June 8, 2012

rake jobs:work fails - delayed_job

 Hello Guys,
       Do you stuck with the problem to execute rake jobs:work during delayed_job implementation? than follow the below steps.
 Rake.rb
In your rails application's Rakefile add few lines.

begin
  gem 'delayed_job', '~>2.0.5'
  require 'delayed/tasks'
rescue LoadError
  STDERR.puts "rake gems:install` to install delayed_job"
end

Also if you want to use the script/delayed_job start command than add delayed_job under lib folder of rails application.

lib/delayed_job

#!/usr/bin/env ruby

require File.expand_path(File.join(File.dirname(__FILE__), '.', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize


Now, you do the rake -T to see that delayed_job task are also embed. Hope you will find useful support via this post.

Friday, April 6, 2012

Combination of array element

Hello Guys,
    Want the combination of array elements using ruby? than use the below custom method.

def arr_combine(arr_1, arr_2)
    return arr_1 if arr_2.empty?
    arr_3 = []
    arr_1.each do |e1|
      arr_2.each do |e2|
        arr_3 << [e1, e2].flatten
      end
    end
    return arr_3
  end

eg. we have array like arr = [[1,2], [3,4,5]]
we expect the result as [[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]] than simply invoke the above method by passing each element of given array.
arr_combine(arr[0], arr[1]) gives you required outcome.

Hope this post will help you out.

Sunday, December 11, 2011

Generate .yml fixtures from database tables

Hello Guys,
          Wondering about how to create fixtures from tables? Here is the simple task which generate .yml from database tables.

namespace :db do
  desc 'Generate .yml test fixtures from an existing database'
  task :generate_fixtures => :environment do
    sql = "Select * From %s"
    skip_tables = ["schema_migrations"]
    ActiveRecord::Base.establish_connection
    tables = ActiveRecord::Base.connection.tables - skip_tables
    tables.each do |table_name|
      count = "0000"
      File.open("#{RAILS_ROOT}/db/fixtures/#{table_name}.yml", 'w') do |file|
        table_content = ActiveRecord::Base.connection.select_all(sql % table_name)
        file.write
table_content.inject({}) { |hash, record|
          hash["#{table_name}_#{
count.succ!}"] = record
          hash
        }.to_yaml
      end
    end
  end
end

When you invoke above task using rake db:generate_fixtures --trace. It generates all the fixtures of your database tables under db/fixtures folder of your rails application.

create_fixtures(fixtures_directory, table_names, class_names = {}) is the inbuilt method available to create fixtures for testing.

Sunday, November 20, 2011

Allow ajax upload

Hello Rubies,
          Do you know how to upload the file through ajax? Last time i was juggling for ajax upload. There is some patch which i have used to allow ajax upload with rails 2.3.x. Follow below instruction to implement it.

Lets, consider the scenario. Where we have content page which has file(.pdf) upload and content area portion.

new.rhtml

<%= form_remote_tag(:url => {:controller => 'contents', :action => 'create'}, :html => { :multipart => true })%>     
    <p id='error_msgs'> </p>
    <p> Content: <%= text_area 'content', 'body' %> </p>
    <p> PDF: <%= file_column_field 'content', 'pdf_path' %> </p>
     <p> <%= submit_tag('Create') %> </p>
</form>
This form allow us to create content along with pdf upload through ajax.

Now want to add some basic validation for file?

class Content < ActiveRecord::Base
   validates_file_format_of :pdf_path , :in => ["pdf"]
   file_column(:pdf_path, :root_path => "#{RAILS_ROOT}/PDFs", :fix_file_extensions => nil)
end

Above we added the validation for file which must be in .pdf format only and store in our application's PDFs directory. You have to assume that your using file column here otherwise you can use normal file_field as well.

In controller of contents we have method called 'create' which need to enhance.

class ContentsController < ApplicationController
   
  def create
     @content = Content.new(params[:content])   
     responds_to_parent do
        if @content.save     
           render :update do |page|
              flash[:notice] = "content created successfully"
              page.redirect_to contents_url
           end
        else
           render :update do |page|
             page.replace_html "error_msgs", "#{error_messages_for :content}"
           end
        end
     end 
  end

end

Here you observed something ?.. we have used the responds_to_parent instead of respond_to block.

Now you guys are wondering about method 'responds_to_parent'. correct?
rails_responds_to_parent  is the method of gem 'rails_responds_to_parent t'. Now install that via
gem install rails_responds_to_parent

For the ajax support we have to add the patch called 'remote_upload' in lib folder of rails application

lib/remote_upload.rb

module ActionView
  module Helpers
    module PrototypeHelper
      alias_method :form_remote_tag_old, :form_remote_tag
      def form_remote_tag(options = {})
         if options[:html] && options[:html][:multipart]     
           uid = "a#{Time.now.to_f.hash}"                               
          <<-STR   
            <iframe name="#{uid}" id="#{uid}" src="about:blank" style="position:absolute;left:-100px;width:0px;height:0px;border:0px"></iframe>
            <form method="post" action="#{url_for options[:url].update({:iframe_remote => true})}" enctype="multipart/form-data" target="#{uid}" #{%(onsubmit="#{options[:loading]}") if options[:loading]}>
           STR
         else
            form_remote_tag_old(options)
         end
      end                            
    end
  end
end

This code will override the prototype's form_remote_tag method and allow iframe support.

Now, we have to include below lines in config/environment.rb to allow access of remote_upload and responds_to_parent

require 'remote_upload.rb'
require 'rails_responds_to_parent'

See our work completed. Now we will freely upload the file through ajax. Find interesting?
If you have any suggestion or query then post the comment.

to get the gem source of rails_responds_to_parent

Wednesday, October 5, 2011

Avoid the memory blockage during large xml request

Guys,
        When i am playing with handling the xml request through net::http discover the problem of memory blockage and just worried about how to handle that. This problem happen b'coze i have bulk of xml data in the request. So, i form the one of the solution by using the block of net http.

When we using the block of net::http. It yields each fragment of the entity body in turn as a string as it are read from the socket.

Lets we consider 2 scenario:

require 'rubygems'
require 'net/https'
require 'uri'
uri = URI.parse("http://google.com")
http = Net::HTTP.new(uri.host, uri.port)

case 1:
response = http.post('http://google.com', 'query=language')

case 2:
# using block
   File.open('test.txt',  'w') { |f|
      http.post('http://google.com', 'query=language') do |str|
          f.write str
       end
   }

In case 1 it loads the entire response in memory. While in case 2 it read each fragment and write into file. so when we use block it's avoid memory blockage.
For more information just follow

Hope above post will help you to avoid memory blockage and increase performance.

Tuesday, October 4, 2011

Content Management System - Browser CMS

Hello rubies,
        I have integrated browser cms in one of the rails application. Awesome to deal with it. Install the browser cms as per your rails version.

If you are using rails below 3 than use browsercms 3.1.2
else use latest version browsercms 3.3.2

After installing cms create the rails application by using command
bcms new project_name -d mysql
cd project_name
rake db:install
rails server

This will create the cms using browsercms. Now you will deal with it by 
adding additional pages, portlets, sections..etc

Want to create in built demo application using browser cms?
bcms demo project_name -d mysql
cd project_name 
rake db:install
rails server

This will create a BrowserCMS project which used MySql as the data
storage. Run the application using http://localhost:3000/cms. and use it's
default user credential cmsadmin/cmsadmin

Get more information regarding browser cms by referring
https://github.com/browsermedia/browsercms/wiki

Monday, October 3, 2011

How to integrate newrelic rpm with rails

Hello,
          If you want to measure the performance (loading time) of your application than use newrelic rpm plugin/gem.

Either install newrelic plugin or gem.

script/plugin install http://newrelic.rubyforge.org/svn/newrelic_rpm
or
gem install newrelic_rpm
Add config.gem "newrelic_rpm" in environment.rb

Now in config edit the newrelic.yml
If you want to monitor application in development mode than set monitor mode

development:
  <<: *default_settings
   monitor_mode: true
   developer_mode: true

Now access the http://localhost:#{port}/newrelic. it shows the time consumption as per request. so from this you will get idea from where most time consumed. Based on that you can optimize the code to save time.


Want to get more information?
follow - https://github.com/mislav/newrelic_rpm

Wednesday, September 21, 2011

Ajax to allow file download

Hello Guys,
          Yesterday i was trying to download the attachment during ajax request. So i find out the some simple way which might help you people.

Below is the controller code snippet:

def download
   file_path = "#{RAILS_ROOT}/test.txt"
   respond_to do |format|
      format.js{
        render :update do |page|
          page.redirect_to :action =>'ajax_download' ,:file => file_path        
        end
      } 
   end
end

def ajax_download
    send_file params[:file]
end

In view i have link for download as:

<%= link_to_remote "Download", :url => {:controller => "test", :action => "download"}%>

Here my parent request is download and than it internally invoke ajax_download action to download attachment.

Friday, September 16, 2011

Read and Write normal text file using ruby

Hello rubies,
        Want to read or write the normal text file using ruby? There is inbuilt File library with ruby. lets we use that and generate simple .txt file and read that.
       
Write .txt file:

Lets we have dummy data:

dummy_data =  [[1,"Ruby on rails","50%"], [2, ".net", "70%"], [3, "java", "80%"]]
File.open("#{RAILS_ROOT}"+"/data.txt", 'w') do |file|
      # set header
         file << "S.No.\tTechnology\tTrend\n"
      # set data
         dummy_data.each do |d|
            file << "#{d[0]}\t#{d[1]}\t#{d[2]}\n"
         end 
end  

Now data.txt is generated in rails_root. lets we read content of .txt file.

file = File.new("#{RAILS_ROOT}/data.txt").read.to_a
data = file.reverse
# pop out the header first
header = data.pop.to_a
h_data = {}
header.each do |h|
  splited_header = h.split("\t")
  splited_header.collect{|h| h_data[h.strip] = []}
end

data.each do |d|
  content =  d.split("\t")
  h_data.keys.sort.each_with_index do |k, index|
    h_data[k] << content[index].strip
  end
end
puts "collected_data : " + h_data.inspect

# find highest trend
max_trend = h_data["Trend"].max
puts "#{h_data['Technology'][h_data['Trend'].index(max_trend)]} has highest(#{max_trend}) trend in IT Market."


This is the simplest way to reach our goal. hope this will help you out.

Saturday, September 3, 2011

Integrate CKEditor in ruby on rails

Hello guys,
                  If you want to integrate WYSIWYG editor then just use simple ckeditor. It much better then any other editors.

Implement CKeditor with rails(2.3.x) application just install
   sudo gem install ckeditor
or configure gem in environment.rb by
   config.gem 'ckeditor', :version => '3.4.3'

Now configure javascript files of ckeditor by
    rake ckeditor:install
and than generate config file for ckeditor.
   rake ckeditor:config

Lets now include ckeditor.js in view

<%= javascript_include_tag :ckeditor %>
<%= ckeditor_textarea 'object', 'field', :toolbar => 'Basic', :width => '100%', :height=> '150px'  %>

so, now run your application and see the ckeditor with basic toolbar. If you want to use additional toolbar then use toolbar as Full. Also there are many other option available like skin and swf_params. It's possible to integrate paperclip along with ckeditor.

Follow https://github.com/jeremy6d/rails-ckeditor to get more information about ckeditor.
Hope this article will help you. If you have any suggestion or query than post comment.

Friday, September 2, 2011

Ajax based pagination

Hello Guys,
          There are different plugin and gem available for pagination. I would like to prefer will_paginate gem for pagination in rails.

First of all we have to add mislav-will_paginate gem via
sudo gem install mislav-will_paginate
 
or specify in your environment.rb

config.gem "mislav-will_paginate", :lib => "will_paginate", :source => "http://gems.github.com"

in your pagination.js add the javascript code to support ajax based pagination

document.observe("dom:loaded", function() {
  var container = $(document.body)

  if (container) {
    # uncomment below code to load spinner
    //var img = new Image
    //img.src = '/images/spinner.jpeg'  
    function createSpinner() {
      //return new Element('img', { src: img.src, 'class': 'spinner' })
    }

    container.observe('click', function(e) {
      var el = e.element()
      if (el.match('.pagination.ajax a')) {
          el.up('.pagination.ajax').insert(createSpinner())
//      if (el.match('.pagination a')) {
//        el.up('.pagination').insert(createSpinner())
        new Ajax.Request(el.href, { method: 'get' })
        e.stop()
      }
    })
  }
})

Now you have to include pagination.js in your view through
<%= javascript_include_tag 'pagination' %>

Lets we implement pagination on index method of users controller.

users_controller.rb

def index
  @users = User.all.paginate(:per_page => 20,:page => params[:page])
  respond_to do |format|
    format.html
    format.js {
      render :update do |page|       
        page.replace_html 'user_list', :partial => 'user_list', :locals => {:users => @users}
      end
    }
    end
end

Now move towards the views. here we have 3 views which listed below.

i) index.html.erb
   <h1> Listing Users </h1>
   <table>
     <tr>
       <th> Name </th>
       <th> Surname </th>
     </tr>
     <tbody id='user_list'>
        <%= render :partial =>'user_list', :locals => {:users => @users} %>
     </tbody>
   </table>

ii) _user_list.html.erb

  <% users.each do |user| %>
    <tr>
      <td> <%= user.name %> </td>
      <td> <%= user.surname %> </td>
    </tr>
  <% end %>
  <tr>
   <td colspan="2"> 
      <%= will_paginate users, :class => 'pagination ajax', :id=>"flickr_pagination"%>
   </td>
  </tr>

iii) index.js.erb
      $("#user_list").html("<%= escape_javascript(render :partial => "user_list") %>");

This is the file which actually play with ajax during pagination.

Now add pagination.css in style sheet for better formatting

#flickr_pagination {
  text-align: center;
  padding: 0.3em 0.3em 0.3em 0.3em;
  clear:both;
  margin:5px 0px 5px 0px;
  }
#flickr_pagination * {
  font: 10pt Arial,Helvetica,Geneva,sans-serif;
  } 
#flickr_pagination a, #flickr_pagination span {
  padding: 0.2em 0.5em; 
  }
#flickr_pagination span.disabled {
  color: #AAA
AAA;
  }
#flickr_pagination span.current {
  font-weight: bold;
  color: #898989; 
  }
#flickr_pagination a {
  border: 1px solid #DDDDDD;
  color: #0072BC;
  text-decoration: none; 
  }
#flickr_pagination a:hover, #flickr_pagination a:focus {
  border-color: #DDDDDD;
  background: #898989;
  color: #FFFFFF; 
  }
#flickr_pagination .page_info {
  color: #aaaaaa;
  padding: 0.8em 0em 0em 0em; 
  }
#flickr_pagination .prev_page, #flickr_pagination .next_page {
  border-width: 1px; 
  }
#flickr_pagination .prev_page {
  margin: 0em 1em 0em 0em; 
  }
#flickr_pagination .next_page {
  margin: 0em 0em 0em 1em; 
  }

you have to include pagination.css in your view through
<%= stylesheet_link_tag 'pagination' %>

Finally we done with ajax pagination. If you want different styles for pagination then just replace the style sheet. http://woork.blogspot.com/2008/03/perfect-pagination-style-using-css.html

Hope this post will help you to implement ajax pagination in rails.

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.