Showing posts with label Ruby on Rails 3. Show all posts
Showing posts with label Ruby on Rails 3. Show all posts

Wednesday, February 29, 2012

Installing Postgresql & using it in rails 3 application

If your are going to build a portal application which is going to hold large data then trust me "Postgresql" is the best option.

1. Install PostgreSql

sudo apt-get install postgresql postgresql-contrib libpq-dev

2. After the installation is complete, create a user (like we create root user in mysql)

sudo -u postgres createuser pgs_root

This will create a user named pgs_root.

3. Now add password to the user

sudo -u postgres psql postgres
running this command will take you to psql prompt

postgres=# \passsword <user>

whatever password you wish to add must be entered twice, then type \q to exit psql prompt.

3. Configure the postgresql.conf file to make PostgreSQL listen to localhost or listen on an external IP or something, change this line to either the IP or '*' or 'localhost'.

/etc/postgresql/8.4/main/postgresql.conf (here 8.4 is the postgresql version, change it if you have installed different version)

under "CONNECTIONS AND AUTHENTICATION" uncomment the following line

listen_addresses = 'localhost'

check whether you have the following line in your /etc/postgresql/8.4/main/pg_hba.conf


# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD


# "local" is for Unix domain socket connections only
local   all         all                               ident
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5

5. Now postgreSQL setup is complete. To use in the application add the "pg" gem in Gemfile

gem "pg"

run bundle install

6.  In order for your application to connect with database present in PostgreSQL, configure it in the database.yml

   development:
    adapter: postgresql
    database: test_postgres
    username: pgs_root
    password: *******
    host: 127.0.0.1

7.  Create the database

    rake db:create

This will create a database named test_postgres in PostgreSQL and it is ready to use.

There is a nice GUI tool for Postgresql named pgadmin3. To install:

sudo apt-get update
sudo apt-get install pgadmin3

All the best...!!!


Using rubyzip in Rails 3

While downloading large files its better to zip it at the server end so that the download becomes much faster.

There is a gem called rubyzip to perform this action.

Add this in your Gemfile

gem "rubyzip", :require => 'zip/zip'

run bundle install

Suppose i have a "folder" which 'has_many' files. So when i try to download the folder, the entire files linked to folder must be downloaded as a zip file. In Folders controller

def download_folder
  @folder = Folder.find(params[:id])
  temp = Tempfile.new("zip-file-#{Time.now}")
  Zip::ZipOutputStream.open(temp.path) do |z|
    @folder.libraries.each do |file|
      z.put_next_entry(file.uploaded_file_file_name)
      z.print IO.read(file.uploaded_file.path)
    end
  end
  send_file temp.path, :type => 'application/zip', :disposition => 'attachment', :filename => "#{@folder.name}.zip"
  temp.delete() #To remove the tempfile
end


Thats it!!!...

Wednesday, January 11, 2012

Implementing 'thumbs_up' gem in Rails application

In one of my application, i came across a feature where i needed to provide the users a option to like or dislike certain things. While searching i came across a gem called "thumbs_up" which was very easy to implement and was quiet good also. let me explain how it can be implemented :

1. Install the gem

gem install thumbs_up

2. Generate thumbs_up migration

rails g thumbs_up

it will generate an model called vote.rb and a migration file to create table.
run the migration

rake db:migrate

3.  Now set the model which acts as voter. for ex. user model will act as voter here

class User < ActiveRecord::Base
  acts_as_voter
end

4. Specify the model which can be voted. for ex. article model can be voted

class Article < ActiveRecord::Base
  acts_as_voteable
end

There can be many models which can be voted in single application not necessary it has to be only one.

5. Specify in the view


<%=link_to image_tag('thumbs_up', :border => 0), vote_for_article_articles_path(@article), :remote => true %>
<%=link_to image_tag('thumbs_down', :border => 0), vote_against_article_articles_path(@article), :remote => true %>

6. In my controller to save the vote

def vote_for_article
    @article = Article.find(params[:id])
    current_user.vote_for(@article)
    respond_to do |format|
      format.js
    end
end

the vote_for method will add a plus vote to the article by current user.

7. Other options

voter.vote_for(voteable) # Adds a +1 vote
voter.vote_against(voteable) # Adds a -1 vote
voter.vote(voteable, vote) # Adds either a +1 or -1 vote: vote => true (+1), vote => false (-1)
positive_vote_count = voteable.votes_for
negative_vote_count = voteable.votes_against

voter.voted_for?(voteable) # True if the voter voted for this object.
voter.vote_count(:up | :down | :all) # returns the count of +1, -1, or all votes
voteable.voted_by?(voter) # True if the voter voted for this object.
voters = voteable.voters_who_voted


By default a user can vote only once, if you wish to change even that can be done. you have to just remove few lines before running migration.

In vote.rb

validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]

and in migration 

add_index :votes, ["voter_id", "voter_type", "voteable_id", "voteable_type"], :unique => true, :name => "uniq_one_vote_only"

That's its all done and it is good to go.....

Tuesday, November 22, 2011

AJAX pagination in rails 3

      We all use will_paginate gem for pagination in our application. However the pagination sends a HTTP request every time when you click on the next page. It will be very nice if the pagination sends an ajax request and update the corresponding <div>, well here it is and its very easy in rails 3... you just have to add few lines in views and controller.

1. In the controller

def index
    @devices = Devices.all.paginate(:page => params[:page] || 1, :per_page => 10)
    .....
    .....

    respond_to do |format|
      format.html
      format.js
    end
end

2. Create a file named index.js.erb in the views and place the following code.

$('#devices').html('<%=escape_javascript(render(:partial => "devices_list"))%>');
$('.pagination a').attr('data-remote', 'true');

3. Put the table which has pagination inside a partial, so that it can be called on each ajax request.

I wish to use pagination in one of my index page, So i will place my table inside a partial  _devices_list.html.erb

<table>
      <thead>
        <tr >
          <th>&nbsp;</th>
          <th colspan="2"><h4>Devices</h4></th>
          <th><%= will_paginate(@devices, :previous_label => "&larr; Previous", :next_label => "Next &rarr;", :inner_window => 1, :outer_window => 1 )%></th>
        </tr>
......
......
</table>

and place this partial inside a div

<div id="devices">
  <%= render :partial => 'devices_list' %>
</div>

4. Add a few lines of jquery inside the script tag in the index page

 <script type="text/javascript">
  $(function() {
    $('.pagination a').attr('data-remote', 'true');
  });
</script>

That's it... it's all done... now you can see an index page which has ajax pagination.If you wish to notify the user that something is happening with a spinner or any hourglass image when the user clicks on the pagination link add the following code.

Add a div which contains the image of the spinner in index file or application.html.erb(This can be used all over the application).

<div id="show_spinner_image" style="display: none">
  <%=image_tag('loader.gif', :border => "0", :style => "float:left;")%> 
</div>

In your application.css

#show_spinner_image{
  position: fixed;
  top: 50%;
  left: 55%;
  margin: -100px 0 0 -100px;
  text-indent: 250px;
  white-space: nowrap;
  overflow: hidden;
}

This CSS will display the spinner at the center of the screen.

Inside the script tag :

<script type="text/javascript">
  $(function() {
     $('.pagination a').click(function(){
         $('#show_spinner_image').show();
        $('.pagination a').attr('data-remote', 'true');
      });
  });
</script>
And at last, in your index.js.erb

$('#devices').html('<%=escape_javascript(render(:partial => "devices_list"))%>');
$('#show_spinner_image').hide();
$('.pagination a').click(function(){
$('#show_spinner_image').show();
$('.pagination a').attr('data-remote', 'true');
     });


Enjoy......