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.

Assets pre compilation error while deploying on heroku

In this post, I am going to address one of the problem I faced while using jquery in my ruby on rails project.

I was using Data Table and Multiselect jquery on my ruby on rails application. It was working fine on my local host. However when I pushed it to github and deployed it on Heroku. It started giving me the following assets pre compilation error.


Your bundle is complete! It was installed into ./vendor/bundle
       Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       could not connect to server: Connection refused
       Is the server running on host "127.0.0.1" and accepting
       TCP/IP connections on port 5432?


The reason for this compilation error can be be anything. I googled it around and found many solution like
  • Solution 1
    Changes in application.rb-In application.rb file, make config.assets.initialize_on_precompile = false. This option prevents the Rails environment to be loaded when the assets:precompile task is executed. Because Heroku precompile assets before setting the database configuration, you need to set this configuration to false or you Rails application will try to connect to an unexisting database.
  • Solution 2
    Assets group in gemfile
    - keeping the jquery gems under assets group in your gemfile.
  • Solution 3
    Check your jquery and css
    - Make sure your css file and jquery files are correct and is in proper format. Even an extra semicolon (;) or brackets will fail the assets pre compliation. Even if you have downloaded a jquery from authentic source it may happen that it have some bugs which will work on local host but not on heroku. (Happened with me)
  • Solution 4
    Remove all the unused jquery from github- It might be possible that you might have been trying many jqueries with your application. You might have pushed this jqueries to github. But later on deleted it from your application in you local machine but didnt do same for the github.
    Use rm command to remove all the unused files.
    Note:- If you think that by deleting files from your local machine and pushing again to github will delete the files from the github also then you are wrong !!! (YES !! I was WRONG). I thought adding, commiting and pushing will remove the files from github also . (Since I am a fresher and new to github, I hope this type of mistake is acceptable :P )
I tried solution 1 2 & 3 but none if them was working. for me. During pre-compliation it was giving me the css error even after I removed all the css files from my local machine and pushed it to heroku.

So yes...I tried the solution 4 removed the conflicting css and jqueries from github and yeah there was no precompliation error !!

So what worked for me was to remove all the unused files css files and jquery files from your local machine and github.