Wednesday 25 September 2013

raw, html_safe,content_tag

raw and html_safe method

They both are used to unescape the html from any string.
    For Example:-
       In your helper method-
         def raw_example()
     raw  "<b>Hello</b>"
         end
     
       In your view
         <%= raw_example %>

      Output:-
         Hello

similarly for html_safe
         def html_safe_example()
     "<b>Hello</b>".html_safe
         end
     
       In your view
         <%= html_safe_example%>

Making it safe from attacks

Suppose you are taking any content from the user then using it with the html_safe to unescape the html like this.
         def html_safe_example(name)
     "<b>Hello #{name}</b>".html_safe
          end

 Lets assume that the content here is "world" everything is good and will work fine. However you have    made your site vulnerable to attacks.What if the user sends any html content instead of his name , suppose "<script>alert("attack")</script>.
To avoid this, instead of writing the whole html content in one line and do it step by step and dont make the name variable as html_safe like this:-

         def html_safe_example(name)
     html = "".html_safe
             html << "<b>Hello".html_safe
             html << name
             html <<"</b>".html_safe
         end

Make sure while concatenating that all the content are html_safe or they all are strings.Else it will give unexpected result.

Content_tag

content_tag returns the html tag of the name provided in the content_tag syntax.
For example:-
-> content_tag(:p, "hi") will return <p>hi</p>
-> content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")


Monday 16 September 2013

Metaprogramming with ruby


1) eval , #{} and their difference.

eval  is used to evaluate the string as expression.
#{} is used to delimit the expressions in a double-quoted string.

At first they both look same however there is a difference between both. Let me explain this with the help of an example.
Suppose we have a variable
exp = "2*4"
Now the output of eval(exp) will be 8
Where as output of  "#{exp}"  will be 2*4

2) instance_eval, module_eval and class_eval

instance_eval can be used to access the instance variable of an object.

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_eval do 
 puts @variable # Output-> hello
end
instance_eval can also be used for creating class methods

For example:-
class Test
end

Test.instance_eval do 
 def hello
   puts "hello world"
 end
end

Test.hello # output => hello world
Like instance_eval, module_eval and class_eval are used to access class variable from outside a class.
Both module_eval and class_eval operates on modules and class rather than their objects.

For Example:-
class Test
 @@variable = "hello"
end

 puts Test.class_eval(@@variable) # Output-> hello
module_eval and class_eval are also used to create new instance methods.
For Example:-
class Test
end

Test.class_eval do 
 def hello
   puts "hello world"
 end
end
obj = Test.new
obj.hello # output => hello world

3) instance_variable_get and instance_variable_set
instance_variable_get, as the name suggests, is used to retrieve the value of any instance variable.
It takes the the variable name as symbol argument

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_variable_get(:@variable) # Output => hello
instance_variable_set, as the name suggests, is used to set the value of any instance variable.
It takes a symbol argument as variable name and second argument which is the variable value

For example:-
class Test
  def initialize
  @variable = "hello"
  end
end

obj = Test.new
obj.instance_variable_set(:@variable,"hello world")
4) send method

send method is used to call a method of the same name as specified as the first argument(which is in symbol format)

For Example:-
@variable = "test"
puts( @variable.send(:reverse)) # this will call the reverse method for that string
You can also pass the any number of arguments after specifying the first argument which is the method name.

For Example:-
class Test
  def sum (a,b)
  return a+b
  end
end

obj = Test.new
obj.send(:sum, 4 , 5) # Output =>9
5) define_method 

This method can be used to define new methods during run time.
For Example:-
 class A
   define_method("test") do ||
     puts "hello"
   end
 end
b= A.new
b.test #output => hello
Another Example:-
Here we are also passing some arguments to the newly created method
 class Array
   define_method(:aNewMethod, lambda{ |*args| puts( args.inspect) } end
[].aNewMethod([1,2,3]) #Ouput [1,2,3]
6) remove_method

You can also remove the existing methods or method you created by using the remove_method.

For Example:-
puts("hello".reverse)
class String
remove_method(:reverse)
end
puts("hello".reverse) # Output => undefined method error!
Note: - If a method with the same name is defined for an ancestor of that class, the ancestor class method is not removed

7) method_missing


There might be the times when you may try to execute a method which is not defined, this will throw an error and cause the program to exit. To handle this situation you can write your own method called method_missing with an argument to which the missing method name is assigned.
class Test
  def method_missing (method_name)
    puts("#{method_name} do not exist")
  end
end

obj = Test.new
obj.new_method # Output = > new_method do not exist

8) Frozen Object
 
Ruby provides you a facility to freeze an object so that it cant be modified further. The object once frozen cannot be modified, if tried to do so it will raise a TypeError exception.
variable = "Hello" 
variable << "world" 
variable.freeze 
variable << " !!!" # Error: "can't modify frozen string (TypeError)"
Please note once an object is frozen it cant be be undone.

Friday 30 August 2013

Git branching and merging

1) git branch
This will list all the branches of your repository in your local.

2) git branch branchname
To create a new branch of your current working repository. Type following code:-

Eg:- git branch newbranch

This will create a new branch in your local..

3) git checkout
This command will switch you to the branch name you entered.

Eg:-git checkout newbranch

4) git checkout -b branchname
This will create a new branch and will switch you to the same.

5) git push origin branchname
Push the branch from local to the github repository.

6) git merge name-of-the-branch-to-be-merged
To merge two branches first checkout the branch to which you want to merge.

Suppose you want to merge the changes from branch A to branch B then do the following:
git checkout B
git merge A

7) git stash
Sometimes you want to switch to some other branch without committing and pushing the changes of the current branch. However you still want to save the changes you have done in that branch. This can be done with the help of stashing.

Suppose you are in branch A and you want to save its changes before switching to branch B.
git stash
This will save the status of the current working directory.

Now you can switch to other branch suppose B
git checkout B
Do the changes, commit it and push it.

Now switch back to branch A
git checkout A
git stash apply //to apply the status u saved before.
git stash apply --index //to reapply the staged changes





Tuesday 27 August 2013

Git Basics

Today I am going to share some of the basic commands of the git.
Starting with a brief description about git :

In software development, Git is a distributed version control and source code management system with an emphasis on speed. Read More
Source:wikipedia

Now coming to commands,I am not going to explain each and every command in detail as the git documentation is enough for that. Will only give brief introduction about them

1) Create your account in github

Goto https://github.com and create your account.

2) Create a repository

Create an empty repository where you want to push the data from your local machine.

Give a name to the repository
A url will be generated for your respository. This is useful in the later process while adding a remote in your local for pushing and pulling purpose. 



3) git init

This command creates an empty git repository.
Suppose you have a folder named "GitTest" in your local. Now you want to push this folder to github then go inside that folder using command line and type "git init".

3) Now add the git remote you created in github.com in your local so that the local changes are pushed to that url .

 git remote add <short name for the url> <url>
 eg : - git remote add origin https://github.com/nikitasingh/GitTest.git

Here origin is the short name for the url

git remote -v will list all the remotes which are added for your repository.

5) Now create some file like "xyz.txt" inside that folder. (Suppose this is the file you want to push to the github)

6) git add

To add the newly created file type-

git add xyz.txt

To add all the files in your folder to github type:-

git add .

7) git commit

File you just added is not ready to be pushed yet, If you will run the git push command without running commit command this file will not be added to your github repository.

so to commit this file type-

git commit -m "first file added" xyz.txt

Here -m is used to give commit messages, you cant run commit command without giving a commit message

8) git push

The next step is to push the changes to the github repository from your local machine. To do that type:

git push origin master

It will ask your login credentials to push the changes.

9) git pull

git pull is used to fetch the changes from the github repository to your local machine.
When two or more people are working on the same repository, it is must to pull the changes so that you have the updated project in your local.

9) git status

If you will type git status it will show the files with following details:-

  •  unmodified files
  •  modified files
  •  added files
  • deleted files
  • renamed files
  • copied files
  • untracked files

Monday 12 August 2013

Difference between collect, select, map and each in ruby

This post is not related to rails part but the RUBY part.

To iterate over an array we generally use collect, select, map and each. As I am beginner I never actually thought what is the difference and I kept using EACH for every loop iteration. However, recently I researched a bit more about these loops and thought to share it . It might help some one I guess  :)

1) Map

Map takes the enumerable object and a block like this [1,2,3].map { |n| n*2 } and evaluates the block for each element and then return a new array with the calculated values.

so the outcome of  [1,2,3].map { |n| n*2 } will be [2,4,6]

If you are try to use map to select any specific values like where n >2 then it will evaluate each element and will output only the result which will be either true or false

so the outcome of  [1,2,3].map { |n| n>2 } will be [false, false, true]

2) Collect

Collect is similar to Map which takes the enumerable object and a block like this [1,2,3].collect { |n| n*2 } and evaluates the block for each element and then return a new array with the calculated values.

so the outcome [1,2,3].collect{ |n| n*2 } of will be [2,4,6]

If you are try to use collect to select any specific values like where n >2 then it will evaluate each element and will output only the result which will be either true or false

so the outcome of  [1,2,3].collect { |n| n>2 } will be [false, false, true]

3) Select

Select evaluates the block with each element for which the block returns true.

so the outcome of  [1,2,3].select { |n| n*2 } will be [1,2,3]

If you are try to use select to get any specific values like where n >2 then it will evaluate each element but returns the array that meets the condition

so the outcome of  [1,2,3].select{ |n| n>2 } will be [3]

4) Each

Each will evaluate the block with each array and will return the original array not the calculated one.
so the outcome of  [1,2,3].each{ |n| n*2 } will be [1,2,3]

If you are try to use each to select any specific values like where n >2 then it will evaluate each element but returns the original array

so the outcome of  [1,2,3].each { |n| n>2 } will be [1,2,3]

Monday 29 April 2013

Using NOKUGIRI gem to parse XML

Nokugiri gem can be used to parse html and xml files. Below is a small tutorial on how to do this in UBUNTU. (Installation procedure for windows is different I gue

1) Add gem "nokogiri" inyour gem file.

2) Run bundle install.

3) To open the xml file use this:-
  doc = Nokogiri::XML(open(filename/URL))

4)Suppose you want to read the content from the folowing xml:-
<first_tag>
<second_tag>Hi XYZ</second_tag>
</first_tag>
To read the content do the following:-
doc.css("first_tag second_tag").map {|node|
                 
        p  tag<<node.children.text
        }

This will output HI XYZ.

5) There are also some other methods which can be used to read the xml like:-

data=doc.xpatch("//first_tag").map do |item|
  [
    item.search("second_tag").first.content
  ]
end

Friday 5 April 2013

Nice twitter bootstrap popup box(modal)

Recently I came across a requirement to have some content on the pop up box when a user clicks on the link. The content can be static or dynamic from the database itself. There are several options that are available like jqbox. However I found twitter bootstrap modal quite useful and attractive.

Refer to the link to know how to use it Twitter Bootstrap modal

To make it dynamic I simply made an ajax call and used the returned JSON object to append the content in the modal. Refer the following to get a brief idea about it.

Code for Twitterbootstrap modal:-



<div id="example" class="modal hide fade in" style="display: none; ">
<div class="modal-header" style="background-color:#CCB647"><h3>  <center><font color="white">Identify the Person!!</font><a class="close" data-dismiss="modal">×</a></center> </h3>
</div>
<div class="modal-body" style="background-color:#D6DEE4">
<div id="game">
<img id="photo" src="" style="width:200px;height:200px;"><br/>
 <div id="options">
 </div>
</div>
</div>
<div class="modal-footer" style="background-color:#CCB647">

Link to open the modal:

<a data-toggle='modal' href='#example' data-backdrop="static" data-keyboard="false" onclick="updatemodal();">
</a>

Script for ajax call:

function updatemodal{
  $.ajax({
   url: '../play/play_game',
   error: function (XMLHttpRequest,textStatus,errorThrown) {
     alert("Something went wrong!! Please try again later. Unable to create options");

   },
   success: function(data){

// Here data is the json object returned by the server
      var jsonObj = $.parseJSON(data);

      $.each(jsonObj,function(key,value){
 
  $('#options').append(value.content);
 
    });

   },
   type: "get"
 });



}


Multiple tab excel sheet using spreadsheet gem


To create multiple sheets in a single excel sheet , its good to use spreadsheet gem. In your controller (suppose card is your controller) add the following:

def export
 
    book = Spreadsheet::Workbook.new
    sheet1 = book.create_worksheet :name => 'Sheet1'
    sheet2 = book.create_worksheet :name => 'Sheet2'

     sheet1.row(0).push "some content in Column1" //to push content in 1st row 1st column of 1st spreadsheet

     //keep pushing on row(0) if you want to push contents other columns of 1st row

      spreadsheet = StringIO.new
      book.write spreadsheet
      file = "Excelsheet"
      send_data spreadsheet.string, :filename => "#{file}", :type =>  "application/vnd.ms-excel"
  end


In you view
<%=link_to("Export Database to Excel", cards_url + "/export")  %>

Wednesday 20 February 2013

Giving name to excel sheet while exporting it- rails 3

You may want to give file name to your excelsheet when you are exporting it. Suppose you want to give the todays date and time as its name. Then do the following:

Suppose export is the method in which you have written the code for exporting excel sheet then do the following:


    def export
       time = Time.now
       time.strftime("%Y-%m-%d %H:%M:%S")
 
      respond_to do |format|
      format.html

      format.xls { headers["Content-Disposition"] = "attachment; filename=\"#{time}"+".xls"}
    end

Tuesday 19 February 2013

Disable browser cache while using devise gem -rails 3

While using devise gem for authentication, I found that even after a user log out, he can still see the previous page he visited if he clicks on the back button of browser. To disable this add the following code in your application_controller.rb.


before_filter :set_no_cache
def set_no_cache


   response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
   response.headers["Pragma"] = "no-cache"
   response.headers["Expires"] = "0"


end

Monday 11 February 2013

Change date format in ruby on rails

Suppose you have date data type and you want to change the format of date being saved from 'yyyy-mm-dd' to 'dd-mm-yyyy' or in any other format then do the following:

Add a file time_defaults.rb in initializers folder and add the  following code


# Default format for displaying dates and times
Date::DATE_FORMATS[:default] = "%d/%m/%Y"
Time::DATE_FORMATS[:default] = "%d/%m/%Y"


And restart the server.

Monday 4 February 2013

Using Dhtmlx datagrid in rails 3 with calendar and combo box (select box)as column type

Earlier I wrote about using a simple dhtmlx data grid in rails 3. The column type was text box which where editable. As I explored it more I found other column types which can be used with datagrid.


Calendar as column type
To use calendar as column type you have to add some of the js and css. These files can be easily downloaded from the dhtmlx website. Download the zip file and copy the below js and css inside your assests javascript and stylesheets folder.

Javascript files:
dhtmlxgrid/codebase/excell/dhtmlxgrid_excell_dhxcalendar.js
dhtmlxgrid/codebasedhtmlxcommon.js
dhtmlxgrid/codebase/calendar/dhtmlxcalendar.js

CSS files:
dhtmlxCalendar/codebase/skins/dhtmlxcalendar_dhx_skyblue.css
dhtmlxgrid/codebase/calendar/dhtmlxcalendar.css


Now while initializating the datagrid specify the  coltype as dhxCalendar


            var grid = new dhtmlXGridObject("grid_here");
            grid.setImagePath("");
            grid.setHeader("Name, Amount");
           
            grid.setColSorting("str,str");
            grid.setInitWidths("150,150");
            grid.setSkin("dhx_skyblue");
            grid.setColTypes("dhxCalendar,ed");

            grid.init();
            grid.load("/decoration/data?decoration="+deco);
            
            dp = new dataProcessor("/decoration/dbaction?decoration="+deco);
            dp.init(grid);

Note:- If you get some error like undefined coltype or somthing. This means that you have not included the correct js. Please check again for all the js files.


Combo box/list box/select box as column type

Specify the setColTypes as "co" if you want to add more options while editing datagrid or else specify "coro" to make it read only.

To add default options to the combo box do the following



      var grid = new dhtmlXGridObject("grid_here");
            
            grid.setImagePath("");
            grid.setHeader("Select number");

            grid.enableMultiselect(true)
            grid.enableLightMouseNavigation(true);
            grid.setInitWidths("100")
            grid.setSkin("dhx_skyblue");
            grid.enableAutoHeight(true);
            grid.enableMultiline(true);
        
            grid.setColTypes("coro");

            var combo1 = grid.getCombo(1); //Here 1 is the id of the column
        
            combo1.put(0,"zero"); // the first data is the value and the second is the data displayed in the dropdown
            combo1.put(2,"two");
    
            grid.init();
      
            grid.load("/visit/data?visit="+deco);
            dp = new dataProcessor("/visit/dbaction?visit="+deco);
            dp.init(grid);



Monday 28 January 2013

'Hisab' Management ;) (Ruby on rails)

I recently developed a small application to track the money in your friend circle. I made this application for my own use. As me and my friends (like everyone) travels a lot. So after coming from a tour  the answer to big question " who will pay who and how much " was quite difficult and hectic. So I tried to make it more easy with the help of this application.

It is developed in rails. The github for the app can be found in here. Just clone it and run rake db:migrate and you are ready to use it.(For ruby on rails user)

Moreover you can also use the application directly.Just go to this link http://hisab.herokuapp.com/.
(Note: The data submitted is right now open for all, so it can be seen by everyone. So I hope you will not enter any confidential data :P )

The app is quite basic right now, but I will enhance it further. Suggestions are most welcome !!!

Demo for the app->

1) Go to  http://hisab.herokuapp.com/.
2) Click on New Event link

3) Enter name of the even and click on submit button.
4) Enter name and the amount the participant paid.

5) Keep on adding the participants and their contribution.

6) The amount a person will get or give will appear.

7) A list will be shown which tells who will give the money to whom.

Wednesday 23 January 2013

Data grid for rails 3 !!

Recently in my project I was trying to use jqgrid or datagrid kind of thing . I selected datagrid and here is the procedure to use it.

Step 1: Generate a controller, say admin


Step 2: Generate a model , say user with three column suppose first_name,last_name,phone


Step 3: Run rake db:migrate


Step 4: Download the jquery from here datagrid. And copy only the 
dhtmlxcommon.js dhtmlxdataprocessor.jsdhtmlxgrid.js and dhtmlxgridcell.js to your app/assests/javascript folder. For css copy the dhtmlxgrid.css and dhtmlxgrid_dhx_skyblue.css in your stylesheet folder.
Also copy the images to your images folder.

Step 5: In controller add an action called view like this :-

        
        class AdminController < ApplicationController
           def view
           end
       end


Step 5: Add a view.html.erb with the following code.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
       
    <body>
        <div id="grid_here" style="width:600px; height:400px;">
        </div>
        <script type="text/javascript" charset="utf-8">
            var grid = new dhtmlXGridObject("grid_here");
            grid.setImagePath("/javascripts/codebase/imgs/");
            grid.setHeader("First name, Last name, Phone");
            grid.setInitWidths("100,100,*");
            grid.setSkin("dhx_skyblue");
            grid.init();
        </script>
        <input type="button" value="Add" onclick="grid.addRow(grid.uid(),'new user')">
        <input type="button" value="Delete" onclick="grid.deleteSelectedRows()">
    </body>
</html>

Step 6: Modify your routes.rb file to add this

resource :admin do
    collection do
      get 'view'
      get 'data'
      get 'dbaction'
    end
  end

If you go to your http://localhost:3000/admin/view you can now see the overall structure of the data grid.

To fill the data with the data grid do the following:


Step 7: Add a new action data in your admin controller

class AdminController < ApplicationController
    def view
    end
    def data
        @users = User.all()
    end
end


Step 8: Add the view part of that action in  /app/views/admin/data.xml.builder

xml.instruct! :xml, :version=>"1.0" 

xml.tag!("rows") do
    @users.each do |user|
        xml.tag!("row",{ "id" => user.id }) do
            xml.tag!("cell", user.first_name)
            xml.tag!("cell", user.last_name)
            xml.tag!("cell", user.phone)
        end
    end
end

Step 9: Add one more line to your view code,

    <script type="text/javascript" charset="utf-8">
            var grid = new dhtmlXGridObject("grid_here");
            grid.setImagePath("/javascripts/codebase/imgs/");
            grid.setHeader("First name, Last name, Phone");
            grid.setInitWidths("100,100,*");
            grid.setSkin("dhx_skyblue");
            grid.init();
            grid.load("/admin/data"); //added !
        </script>

To save grid data do the following:-

Step 10: Add one more action dbaction to your controller-


class AdminController < ApplicationController
    def view
    end
    def data
        @users = User.all()
    end
    def dbaction
        #called for all db actions
        first_name = params["c0"]
        last_name    = params["c1"]
        phone            = params["c2"]
        
        @mode = params["!nativeeditor_status"]
        
        @id = params["gr_id"]
        case @mode
            when "inserted"
                user = User.new
                user.first_name = first_name
                user.last_name = last_name
                user.phone = phone
                user.save!
                
                @tid = user.id
            when "deleted"
                user=User.find(@id)
                user.destroy
                
                @tid = @id
            when "updated"
                user=User.find(@id)
                user.first_name = first_name
                user.last_name = last_name
                user.phone = phone
                user.save!
                
                @tid = @id
        end 
    end

end 

Step 11: For this dbaction add the view part in  /app/views/admin/dbaction.xml.builder


xml.instruct! :xml, :version=>"1.0" 

xml.tag!("data") do
    xml.tag!("action",{ "type" => @mode, "sid" => @id, "tid" => @tid }) 
end


Step 12: Modify the view.html.erb file like this


    <script type="text/javascript" charset="utf-8">
            var grid = new dhtmlXGridObject("grid_here");
            grid.setImagePath("/javascripts/codebase/imgs/");
            grid.setHeader("First name, Last name, Phone");
            grid.setInitWidths("100,100,*");
            grid.setSkin("dhx_skyblue");
            grid.init();
            grid.load("/admin/data");
            
            dp = new dataProcessor("/admin/dbaction/");
            dp.init(grid);

        </script>


Step 13: Go to http://localhost:3000/admin/view and now you can see the the data grid with add and delete functionality




Point to be noted:-
  • Make sure  you change the path of the images in the css file so that images gets refelected in your view part.
  • This is just a basic example, more functionalty can be added if you refer to the documentaion of the datagrid


Monday 21 January 2013

Importing an excelsheet -ruby on rails

I recently used roo gem for importing an excel sheet into your ruby on rails application.
Below are the steps for it :

Step 1: Add the line gem 'roo' in your gem file
Step 2: Run bundle install
Step 3:Add a method in your controller :-
Suppose your controller name is Decoration
          
def import
  Decoration.import(params[:file])
  redirect_to root_url, notice: "decorations imported."
end

Step 4: In your model add the import method as follows:
Here your model name is Decoration

def self.import(file)
  spreadsheet = open_spreadsheet(file)
  header = spreadsheet.row(1)
  (2..spreadsheet.last_row).each do |i|
    row = Hash[[header, spreadsheet.row(i)].transpose]
    decoration = find_by_id(row["id"]) || new
    decoration.attributes = row.to_hash.slice(*accessible_attributes)
    decoration.save!
  end
end

def self.open_spreadsheet(file)
  case File.extname(file.original_filename)
  when ".csv" then Csv.new(file.path, nil, :ignore)
  when ".xls" then Excel.new(file.path, nil, :ignore)
  when ".xlsx" then Excelx.new(file.path, nil, :ignore)
  else raise "Unknown file type: #{file.original_filename}"
  end

Step 5 :In the config/application.rb file add this line:

require 'iconv'
 

Step 6: Add this this line to your routes.rb file

resources :decorations do
  collection { post :import }
end

Step7: Add the interface for importing the excel file using below lines:

<%= form_tag import_decorations_path, multipart: true do %>
  <%= file_field_tag :file %>
  <%= submit_tag "Import" %>
<% end %>


Note: Only. xls file can be imported using the above method.

Friday 18 January 2013

How to read parameters from URL


Suppose your URL is -- > http://localhost:3000/decorations/expense?decoration=32

Step 1: Add a function inside your js file


function getUrlVars() {
    var vars = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
        vars[key] = value;
    });
    return vars;
}


Step 2: Retrieve the data in a variable by using below line


var deco = getUrlVars()["decoration"];

Tuesday 15 January 2013

Testing paperclip with rspec

This post cover the basic testing of paper clip gem in the controller. Since I am new to rspec so I may not be able to cover it in detail with many test cases now but for beginners, I hope its useful.

Suppose you are testing the new function of your controller then the steps will be like this:

  1.  Add a describe in your decorations_controller_rspec.rb.
    Note: Decoration here is the name of my controller, which creates a decoration with a name, year of that decoration and expense.Expense here is an excel sheet which is getting uploaded through paperclip gem.

    describe "#new" do
        it "must take 4 parameter and returns a decoration object" do
         get "new"
            @decorations=Decoration.new(:name=>'decoration',:year=>'2012',:zone_id=>'1',:expense=> File.new(Rails.root + 'spec/fixtures/test.xls'))
           @decorations.should be_an_instance_of Decoration
        end
    end
  2. Create a folder fixtures inside spec directory of your application and add any xls file suppose test.xls. 
  3. Its done. You rspec will pass the test case.


Monday 14 January 2013

Exporting table as Excel Sheet and CSV on ruby on rails

In this post I am not going to brief you on how to export any table as Excel Sheet and CSV in ruby on rails.
It can be found in this link--> Exporting as CSV and EXcel Sheet

I will address the problem which I faced while using it.

Problem

I followed  all the steps mentioned in the link and everything seems to be working fine.
There was no exception and even the download link was working fine.

However when I downloaded the excel file and opened it, the data in the files was not the content of the table . Rather the excel sheet was rendering the lists of objects like this-
#<Colleague:0x35e1e20>,
 #<Colleague:0x35e19d0>



Solution

In controller, instead of using @colleagues i.e the instance variable use the model name instead like this.

Note:- It may happen that you are able to export an excel sheet without this solution also. But if you are not  try this !!

Replace this: 

  format.csv { send_data @colleagues.to_csv }
  format.xls { send_data @colleagues.to_csv(col_sep: "\t") }
With

 format.csv { send_data Colleague.to_csv }
 format.xls { send_data Colleague.to_csv(col_sep: "\t") }

Some tips:
  • Make sure to restart the server after changing the config files.
  • Gems like spreadsheet are also available which can be used for this same purpose.