codedecoder

breaking into the unknown…


Leave a comment

require_tree require_self in asset_pipeline

Assets Pipeline introduced with rails 3, combines all the js file into one application.js file and all css files into one application.css file.

=> Understanding application.js and application.css in rails

application.js and application.css are manifest file in rails . A manifest file is a file which simply enumerates the files which are included in the distribution, either for processing by various packaging tools, or for human consumption.

When you create a new rails 3 application, you will find app/assets folder containing javascript, stylesheet and images folder within it.

within stylesheet folder you will find application.css file with below content

/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
 * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the top of the
 * compiled file, but it's generally better to create a new file per style scope.
 *= require_self
 *= require_tree .
 */

Similarly, you can find application.js file in javascript folder with the below content

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require_tree .

So, We will try to figure out the term require require_self and require_tree .

require is like usual ruby require which make a file accessible within the file it is called. The file path will be relative and will be searched in path : lib/assets/javascripts, vendor/assets/javascripts, or vendor/assets/javascripts for javascript and lib/assets/stylesheet, vendor/assets/stylesheet, or vendor/assets/stylesheet for stylesheet . Further you do not need to provide extension of the file as it assume stylesheet will contain .css files and javascript will contain .js file. Anyway, it will not complain if you provide the extension also .

require_self tell the asset pipeline to include the file within which it is used i,e here it is telling the asset pipeline to include application.css file also while precompiling the css assets . It means if you write any css within application.css (avoid it , it is against convention) that will also get reflected.basically, since we are not writing any css within application.css, removing require_self will not make any difference.

require_tree will tell asset pipeline to include all the files within the specified directory. By default it is set to current directory with . (i,e dot) . So say you have bootstrap.min.css and bootstrap_responsive.min.css file in app/assets/stylesheet folder, then the require_tree . will automatically load them. Now say you have put your all custom css file in app/assets/custom_css folder, then you can load them by writing another require_tree as below

 *= require_self
 *= require_tree .
 *= require_tree ../custom_css

So first require_tree will load all css from current directory i,e stylesheet folder and second one will from custom_css folder.

NOTE : require_tree load all the file from the specified directory, but in random order, mostly in alphabetically order. Be careful ,  as css and js files are dependent on the order in which they are called

=> Loading css or js file in specific order
Js files are dependent on the order in which they are called. For example let you have jquery.min.js , bootstrap.min.js ,

bootstrap_responsive.min.js and custom.js file in app/assets/javascript folder. But say in application.js you write

//= require_tree .

It will load all the above files for you, but not in desired order. So for the file which need in order use require, as then they will be called in the order they are called. So below is the correct way of specifying the file.

 //= require jquery.min.js 
 //= require bootstrap.min.js
 //= require bootstrap-responsive.js
 //= require_tree .

So, the file with require will be called in same order, and then all other file will be called. Also you may call require_tree at any position. See another example below of application.css from one of my application

 *= require jquery.loader-min
 *= require ui.jqgrid
 *= require_tree .
 *= require jquery-ui/dark-hive
 *= require themes/cyborg/css/bootstrap.min.css
 *= require themes/cyborg/css/bootstrap_and_overrides.css
 *= require_self

I have called, some files after require_tree , as those are files in vendor directory and I want them to be called, after all css file in current directory is loaded.

NOTE : require_tree do not include files which are already called by require . Further If you want you can call all the files with require and then you will not need require_tree.

 

 

REFERENCE :

http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives


6 Comments

bootstrap drop down-menu not working with rails

Recently, a trainee learning bootstrap comes to me for help asking why the bootstrap drop down menu not working. It took me about 20 minutes to figure out the issue. As usual first I tried to see that the HTML structure or markup of menu  as required by Bootstrap dropdown .

The structure used by the trainee is as below and it look fine.

<div class="nav-collapse collapse">

   <ul class="nav pull-right">

      <li class="dropdown">

          <a href="/product_and_services" class="dropdown-toggle" data-toggle="dropdown">
                                     Products and Services<b class="caret"></b>
          </a>

          <ul class="dropdown-menu">

             <li class="nav-header">PRODUCTS</li>

             <li><a href="product.html">Product1</a></li>

             <li><a href="product.html">Product2</a></li>

             <li><a href="product.html">Product3</a></li>

             <li><a href="all_products.html">All products</a></li>

             <li class="divider"></li>

             <li class="nav-header">SERVICES</li>

             <li><a href="service.html">Service1</a></li>

            <li><a href="service.html">Service2</a></li>

            <li><a href="service.html">Service3</a></li>

            <li><a href="all_services.html">All services</a></li>

        </ul>

     </li>

     <li class="dropdown">

        <a href="/about" class="dropdown-toggle" data-toggle="dropdown">About<b class="caret"></b></a>

        <ul class="dropdown-menu">

           <li><a href="our_works.html">Our works</a></li>

           <li><a href="patnerships.html">Parnerships</a></li>

           <li><a href="leadership.html">Leadership</a></li>

           <li><a href="news.html">News</a></li>

           <li><a href="events.html">Events</a></li>

           <li><a href="blog.html">Blog</a></li>

        </ul>

     </li>

     <li><a href="faq.html">FAQ</a></li>

     <li><a href="/contact_us">Contact us</a></li>

     <li><a href="signup.html">Sign up</a></li>

     <li><a href="signin.html">Sign in</a></li>

   </ul>

</div>

So structure is O.K, with Product and Services, and About menu having sub menu within them. By default bootstrap behaviour,  when user click on these two menu the sub menu should appear. But it is not working.

let us try to trigger it manually on firebug console.

$('.dropdown-toggle').dropdown()
TypeError: $(...).dropdown is not a function

O.k show we now know the problem : the dropdown() function is not getting called

Now it may happen due to any of the below reason .

Reason 1: you forget to add bootstrap-dropdown.js file
This is possible if you are using individual js component of bootstrap rather than bootstrap.js or bootstrap.min.js.
but in our case we are using jquery.min.js file, so it is sure that all required js component is included.

Reason 2: jquery.js file is added after  the bootstrap file
the bootstrap.js file is dependent on jquery.js , so jquery.js file must be added before bootstrap.js file.
In rails you can define it in application.js file. My application.js file look like this

//= require jquery
//= require jquery_ujs
//= require_tree .

So here. we have included jquery at the top then jquery_ujs and then we have done require_tree . which will automatically include all the files within app/assets/javascript folder. Currently this folder contain application.js, bootstrap.min.js , jquery.min.js and custom.js file, so all of them will be included in the alphabetical order. the application.js file will be rendered in the end. You can see it by viewing page source. The js are rendered in below sequence as shown in the page source.

<script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/boot-business.js?body=1" type="text/javascript"></script>
<script src="/assets/bootstrap.min.js?body=1" type="text/javascript"></script>
<script src="/assets/custom.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery.min.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>

So we can see that jquery.js file is at the top, so this is also not the cause of our problem

Reason 3: jquery or bootstrap file is included more than once
So this is the cause of our problem. You can easily see from the above page source that jquery is included twice, one at the top as jquery.js and again at the second last line as jquery.min.js. Now why this happened . Actually,  //= require jquery line in application.js file load the jquery from jQuery-rails gem which is now shipped as default with rails 3. But the trainee, following the bootstrap tutorial also added jquery.min.js file in the app/assets/javascript folder, which get rendered by //= require_tree . directive.

=> Triggering bootstrap dropdown menu on hover

By default, bootstrap dropdown get triggered on click , but you can make it to open on hover by adding below code, I have added it to custom.js file

$(document).ready(function(){
    $('.navbar .dropdown').hover(function() {
        $(this).find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
    }, function() {
        $(this).find('.dropdown-menu').first().stop(true, true).delay(100).slideUp()
    });
})


1 Comment

routes in rails

routes in rails is basically a URL, which user type in the browser to access any particular part of your application. routes is defined in configuration/routes.rb  file. This file contain all the URL of your Application. Rails provide you a number of concise way to define a URL or a route in rails term.

To get the list of all the routes available in your application, run below command on your project directory

$ rake routes # it will list all the routes in your application

OR

$ bundle exec rake routes # It is same as above command, we are just running it in context of current bundle. the above command may cause problem some time, but this will always work. get more detail on bundle exec in this post.

If you are working on ubuntu, you can filter the listed routes with grep command as below

$ bundle exec rake routes | grep photos # It will list only the route containing photos.

photos               GET                   /photos(.:format)                     photos#index
                     POST                  /photos(.:format)                     photos#create
new_photo            GET                   /photos/new(.:format)                 photos#new
edit_photo           GET                   /photos/:id/edit(.:format)            photos#edit
photo                GET                   /photos/:id(.:format)                 photos#show
PUT                                        /photos/:id(.:format)                 photos#update
DELETE                                     /photos/:id(.:format)                 photos#destroy

O.K……….now how you will read them.

First column : It represent named_helper, which you can use in you view file

NOTE : you can use the named_helper either with path or url suffix. with path suffix it generate the relative path while with url suffix it  will generate the absolute path. So, for  a example you can use new_photos_path or new_photos_url.

Second Column : It will tell about HTTP verb.

NOTE : same named route may go to different action depending on the verb passed to it. for example photos_path + GET combination will go to index action of photos controller while photos_path + POST combination will go to create action of photos controller

Third Column : It represent the URL the user will type in the browser

Fourth Column : It represent the controller#action combination i,e photos#index means the /photos url with GET verb will go to index action of photos controller

So. now we will see the rails way of defining routes in configuration/routes.rb file

=> Resource full routes or Resource Routing

In rails each controller is a resource and Rails being restful assume that each resource will definitely have index, show, new, create, edit, update and delete action. So rails can generate 7 url for you, by just single line below

resources :photos # it will generate the 7 routes for photos which I have already discussed above

resources :books # it will generate the 7 routes for photos which I have already discussed above

You can also generate multiple resources at the same time. So instead of two line above you can define them in single line as below

resources :photos, :books, :videos

=>  Nested Resources

It will reflect your model relation, say

class Magazine < ActiveRecord::Base
   has_many :ads
end

class Ad < ActiveRecord::Base
   belongs_to :magazine
end

This can be captured in your routes like

resources :magazines do
   resources :ads
end

The generated routes are:

HTTP Verb          Path                          action         named helper
----------------------------------------------------------------------------------------------------
GET                 /magazines/:id/ads             index         magazine_ads_path(@magazine)
GET                 /magazines/:id/ads/new         new           new_magazine_ad_path(@magazine)
POST                /magazines/:id/ads             create        magazine_ads_path(@magazine)
GET                 /magazines/:id/ads/:id         show          magazine_ad_path(@magazine, @ad)
GET                 /magazines/:id/ads/:id/edit    edit          edit_magazine_ad_path(@magazine, @ad)
PUT                 /magazines/:id/ads/:id         update        magazine_ad_path(@magazine, @ad)
DELETE              /magazines/:id/ads/:id         destroy       magazine_ad_path(@magazine, @ad)

Note:  that here you are passing magazine id in all & ads id as required wherever in normal case. Also as good rails practice avoid more then one level nesting like below as it become very cumbersome.

resources :publishers do
          resources :magazines do
                         resources :photos
      end
end

=> Non-Resourceful Routes

They are basically not associated with any resource but are common route which resolve the url to a controller and action by itself

match ‘:controller(/:action(/:id))’ #since :action and :id are optional parameters, denoted by parentheses.

When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: :controller maps to the name of a controller in your application, and :action maps to the name of an action within that controller. For example, consider one of the default Rails routes:

match ‘:controller(/:action(/:id))’

If an incoming request of /xyz/fgh/1 is processed by this route (because it hasn’t matched any previous route in the file), then the result will be to invoke the fgh action of the xyzController, and to make the final parameter “1” available as params[:id]. This route will also route the incoming request of /xyz to xyzController#index,

Also, dynamic segment can take any thing.

match ‘:controller/:action/:id/:user_id’ #you can expand it to pass any no of params

You can’t use namespace or :module with a :controller path segment.

If you need to do this then use a constraint on :controller that matches the namespace you require. e.g:

match ‘:controller(/:action(/:id))’, :controller => /admin\/[^\/]+/

By default dynamic segments don’t accept dots – this is because the dot is used as a separator for formatted routes.If you need to use a dot within a dynamic segment add a constraint which overrides this – for example
:id => /[^\/]+/  # allows anything except a slash.

You can specify static segments when creating a route:
match ‘:controller/:action/:id/with_user/:user_id’ # here with_user is the static segment. those which do not start with : is treated as static

The params will also include any parameters from the query string. For example, with this route:
match ‘:controller/:action/:id’

An incoming path of /photos/show/1?user_id=2 will be dispatched to the show action of the Photos controller. params will be { :controller => “photos”, :action => “show”, :id => “1”, :user_id => “2” }.

You can also define other defaults in a route by supplying a hash for the :defaults option. This even applies to parameters that you do not specify as dynamic segments. For example:
match ‘photos/:id’ => ‘photos#show’, :defaults => { :format => ‘jpg’ }

Rails would match photos/12 to the show action of PhotosController, and set params[:format] to “jpg”.

=> Naming Routes or Named Routes

In the above case of non resourceful routes we are specifying the controller and action name in the url itself  by using match keyword.Let us take another example of non resourceful routes.

match “sessions/destroy” # it will try to take the user to destroy action of session controller

what if we want that the user type “/exit” in browser and he is taken to destroy action of session controller . You can further specify any specify name for any route using the :as option. This is called a named routes. see the example below

match ‘exit’ => ‘sessions#destroy’, :as => :logout

This will create logout_path and logout_url as named helpers in your application. Calling logout_path will return /exit

You can further add, various options to a named routes

=> HTTP Verb Constraints

You can use the :via option to constrain the request to one or more HTTP methods:
match ‘photos/show’ => ‘photos#show’, :via => :get

There is a shorthand version of this as well:
get ‘photos/show’

You can also permit more than one verb to a single route:
match ‘photos/show’ => ‘photos#show’, :via => [:get, :post]

=> Segment constraint
You can use the :constraints option to enforce a format for a dynamic segment:

match ‘photos/:id’ => ‘photos#show’, :constraints => { :id => /[A-Z]\d{5}/ }

This route would match paths such as /photos/A12345. You can more succinctly express the same route this way:
match ‘photos/:id’ => ‘photos#show’, :id => /[A-Z]\d{5}/

:constraints takes regular expressions with the restriction that regexp anchors can’t be used.
For example, the following route will not work:
match ‘/:id’ => ‘posts#show’, :constraints => {:id => /^\d/}

However, note that you don’t need to use anchors because all routes are anchored at the start.

For example, the following routes would allow for posts with to_param values like 1-hello-world that always begin with a number and users with to_param values like david that never begin with a number to share the root namespace:

match ‘/:id’ => ‘posts#show’, :constraints => { :id => /\d.+/ }
match ‘/:username’ => ‘users#show’

=> Request-Based Constraints

You can also constrain a route based on any method on the Request object that returns a String.

You specify a request-based constraint the same way that you specify a segment constraint:
match “photos”, :constraints => {:subdomain => “admin”}

You can also specify constraints in a block form:

namespace :admin do
      constraints :subdomain => "admin" do
             resources :photos
      end
end

=>Advanced Constraints

If you have a more advanced constraint, you can provide an object that responds to matches? that Rails should use. Let’s say you wanted to route all users on a blacklist to the BlacklistController.

You could do:

class BlacklistConstraint
    def initialize
       @ips = Blacklist.retrieve_ips
    end

    def matches?(request)
      @ips.include?(request.remote_ip)
    end
end

Now, you can pass the object of the above class in the routes

TwitterClone::Application.routes.draw do
   match "*path" => "blacklist#index", :constraints => BlacklistConstraint.new
end

=> Member route & collection route
You can create, any other route apart from the default restful action in a controller Use member if you do not need to pass id to controller action

resources :photos do
    member do
         get 'preview'
         put 'adjust_size'
     end
end

This will recognize /photos/1/preview with GET, and route to the preview action of PhotosController. It will also create the preview_photo_url(@photo) and preview_photo_path(@photo) helpers.Note that you have to pass the id of photo

Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use get, put, post, or delete here. If you don’t have multiple member routes, you can also pass :on to a route, eliminating the block:

resources :photos do
   get 'preview', :on => :member
end

To add a route to the collection:

resources :photos do
     collection do
            get 'search'
      end
end

This will enable Rails to recognize paths such as /photos/search with GET, and route to the search action of PhotosController. It will also create the search_photos_url and search_photos_path route helpers.

Just as with member routes, you can pass :on to a route:

resources :photos do
   get 'search', :on => :collection
end

Note that, in collection routes we do not pass an ID, basically it is used for action which is going to operate on collection say all photos rather than the individual as in case of preview member of photo, as through id we need to find preview of which photo.

=> Controller Namespacing
Sometime you want to group a set of controller within one folder for example you may want to put all the  admin controller  in admin folder within the controller folder. this is called controller namespacing. all the controller within this admin folder have admin::name_of_controller format

Case 1: the default namespacing

namespace :admin do
    resources :posts, comments
end

It will generate routes like

HTTP Verb               Path                    action                 named helper
------------------------------------------------------------------------------------------
GET                    /admin/posts             index                  admin_posts_path
GET                    /admin/posts/new         new                    new_admin_post_path
POST                   /admin/posts             create                 admin_posts_path
GET                    /admin/posts/:id         show                   admin_post_path(:id)
GET                    /admin/posts/:id/edit    edit                   edit_admin_post_path(:id)
PUT                    /admin/posts/:id         update                 admin_post_path(:id)
DELETE                 /admin/posts/:id         destroy                admin_post_path(:id)

So not much difference, exactly same as normal case except routes are prefixed by admin, the name space

case 2 : If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use

scope :module => "admin" do
     resources :posts, comments
end

or, for a single case (it means one statement in one line)

resources :posts, :module => "admin"

It will generate named helper exactly as above but url will not have admin/ prefix

Case 3: You want to namespace the routes only, to say that you do not placed posts within admin folder i,e it is normal controller without any admin:: prefix or to say it is in admin folder but do not have that prefix but basically you want to draw your routes as above

i,e If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use

scope "/admin" do
   resources :posts, :comments
end

or, for a single case

resources :posts, :path => "/admin/posts"

It will generate routes same as above but name helper will not have admin prefix
=> Route Globbing

Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example

match ‘photos/*other’ => ‘photos#unknown’

This route would match photos/12 or /photos/long/path/to/12, setting params[:other] to “12” or “long/path/to/12”.

Wildcard segments can occur anywhere in a route. For example,

match ‘books/*section/:title’ => ‘books#show’

would match books/some/section/last-words-a-memoir with params[:section] equals “some/section”, and params[:title] equals “last-words-a-memoir”.

Technically a route can have even more than one wildcard segment. The matcher assigns segments to parameters in an intuitive way. For example,

match ‘*a/foo/*b’ => ‘test#index’

Starting from Rails 3.1, wildcard routes will always match the optional format segment by default.For example if you have this route:

match ‘*pages’ => ‘pages#show’

By requesting “/foo/bar.json”, your params[:pages] will be equals to “foo/bar” with the request format of JSON. If you want the old 3.0.x behavior back, you could supply :format => false like this:

match ‘*pages’ => ‘pages#show’, :format => false

If you want to make the format segment mandatory, so it cannot be omitted, you can supply :format => true like this:

=> Routing to Rack Applications

Instead of a String, like “posts#index”, which corresponds to the index action in the PostsController, you can specify any Rack application as the endpoint for a matcher.

match “/application.js” => Sprockets

As long as Sprockets responds to call and returns a [status, headers, body], the router won’t know the difference between the Rack application and an action.

For the curious, “posts#index” actually expands out to PostsController.action(:index), which returns a valid Rack application.

=> Using root

You can specify what Rails should route “/” to with the root method:
root :to => ‘pages#main’

You should put the root route at the top of the file, because it is the most popular route and should be matched first. You also need to delete the public/index.html file for the root route to take effect.

Referance :

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


2 Comments

proc and lambda in ruby

In this post I have explained about ruby block, read it if you are not clear about block before proceeding further. Here we will try to understand Proc in ruby. ruby documentation define it as below .

“Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.”

Forget it if you do not understand a bit of the definition. I will explain it in simpler way as we proceed. To get a better idea of any programming concept you must ask two question : why and when .

So here we have the question, why to use Proc and when to use Proc. Iet us figure it out. I can’t visualize any better scenario, so I will stick to the case when we have to welcome peoples from different part of India.
Let us write our code in proc_demo.rb file.

Example 1:  Creating Proc object, storing it in  variables and passing it to a method

punjab = Proc.new do |person|
  puts "Hi....#{person}...how are you?"
  puts "I welcome you as per punjab tradition"
  puts "I will serve you makki di roti with sarson di saag"
end

tamil = Proc.new do |person|
  puts "Hi....#{person}...how are you?"
  puts "I welcome you as per tamil tradition"
  puts "I will serve you idli and curd rice"
end

mumbai = Proc.new do |person|
  puts "Hi....#{person}...how are you?"
  puts "I welcome you as per mumbai tradition"
  puts "I will serve you bada pav and pav bhaji"
end

def welcome(guest, proc_obj=nil)
  puts "I am the head of family"
  proc_obj.call(guest) if proc_obj
  puts "Let me introduce you to my family"
end

puts "*********OUTPUT of welcome('arun' , punjab)*************"
welcome("arun" , punjab) # arun is the local variable and punjab the variable containing proc object
puts "*********OUTPUT of welcome('arun' , mumbai)*************"
welcome("arun" , mumbai) # arun is the local variable and mumbai the variable containing proc object
puts "*********OUTPUT of welcome('arun' , mumbai)*************"
welcome("rama swamy" , tamil) # rama swamy is the local variable and tamil the variable containing proc object

run this file from your terminal with ruby keyword as below and see the output .

arun@arun-yadav:~$ ruby   “/home/arun/proc_demo.rb”
*********OUTPUT of welcome(‘arun’ , punjab)*************
I am the head of family
Hi….arun…how are you?
I welcome you as per punjab tradition
I will serve you makki di roti with sarson di saag
Let me introduce you to my family
*********OUTPUT of welcome(‘arun’ , mumbai)*************
I am the head of family
Hi….arun…how are you?
I welcome you as per mumbai tradition
I will serve you bada pav and pav bhaji
Let me introduce you to my family
*********OUTPUT of welcome(‘rama swamy’ , tamil)*************
I am the head of family
Hi….rama swamy…how are you?
I welcome you as per tamil tradition
I will serve you idli and curd rice
Let me introduce you to my family

We can summarize below things about Proc from the above example.

=> Proc object can be created in two way : Proc.new or lambda. we have used Proc.new above, but you can use lambda also. lambda is stricter implementation of Proc object. we will come to the difference later on.
=> Proc are object which wrap in the block passed to it
=> once created proc object can be stored in a variable, can be used in any method directly, can be passed as a argument to any method
=> the block within proc object can be executed by call() method
=> the proc object bind itself to the local variables of the method in which it is called. for example : in above output you can see that the person name passed to the method is used by the proc object.
=> Proc object look similer to method in its implementation, but looking deeper, below is the major difference
        -> method can’t be passed to another method but proc can be passed to any method
        -> method can return a value but can’t return another method but Proc can return another method.

=> So we can conclude that, Proc provide better flexibility as compared to a method, which explain why we should use it. Now coming to when…we should use Proc whenever, a piece of code within any method need to behave differently in different situation. In above case the welcome message varies according to state from which the person is coming.

Example 2: Creating Proc object directly within the method.

As I have mentioned above we can create Proc object in two ways. Above example used Proc.new, so now we will use lambda. In whichever way you are creating the Proc object, you should always pass a block to it. If NO block is passed to proc object, It will try to execute the block passed to the method within which it is called. If the method also do not have any block passed to it, It will throw error when proc object is called. Let us illustrate it . write below code to proc_demo.rb file.

def welcome(guest)
  puts "I am the head of family"
  message = lambda # proc object is created with lambda but no block is passed
  message.call(guest) # the proc object executed with call()
  puts "Let me introduce you to my family"
end

puts "*********OUTPUT of method call with a block*************"
welcome("arun"){|person| puts "Hi #{person}.....how are you"}
puts "*********OUTPUT of method call without a block*************"
welcome("arun")

run the above ruby file and see the output :

arun@arun-yadav:~$ ruby /home/arun/proc_demo.rb
*********OUTPUT of method call with a block*************
I am the head of family
/home/arun/Documents/books/learn_ruby/proc_demo.rb:4: warning: tried to create Proc object without a block
Hi arun…..how are you
Let me introduce you to my family
*********OUTPUT of method call without a block*************
I am the head of family
/home/arun/Documents/books/learn_ruby/proc_demo.rb:4:in `lambda’: tried to create Proc object without a block (ArgumentError)
from /home/arun/Documents/books/learn_ruby/proc_demo.rb:4:in `welcome’
from /home/arun/Documents/books/learn_ruby/proc_demo.rb:12:in `’

So here we have created the Proc object directly within the method. you can see that if block is not passed to proc object and also not available in method where it is called it throw error.

Example 3: Method which return Proc object.
In both the example above, you can see that the Proc object is called within the method itself. But you can make any method to return a Proc object. It is also a major point which emphasise why and when we should use a Proc instead of method. Note that a method can return a value but can’t return another method, but it can return a Proc object.

def multiply_val(num)
  return Proc.new{ |n| n*num}
end

puts "**OUTPUT with different argument value of multiply_val() and call()**"
puts multiply_val(3).call(5)
puts multiply_val(3).call(12)
puts multiply_val(7).call(12)

Now see the output of above program.

arun@arun-yadav:~$ ruby /home/arun/proc_demo.rb
**OUTPUT with different argument value of multiply_val() and call()**
15 # multiplication of 3 passed to the method and 5 passed to the block in Proc object
36 # multiplication of 3 passed to the method and 12 passed to the block in Proc object
84 # multiplication of 7 passed to the method and 12 passed to the block in Proc object

So here, you can see that Proc object is called not within the method but outside it as the method is returning a Proc object. when you write multiply_val(3), it return a Proc object which is bounded to the local value 3 passed to the method. Then you simply execute that object with call()

DIFFERENCE BETWEEN PROC and LAMBDA :

As you have seen above, both Proc.new and lambda is used to create Proc object. lambda is stricter implementation of Proc object. These are the main defference:

=> lambda raise exception if required number of argument is not passed .

NOTE : You can use proc for Proc.new . proc is shorthand of Proc.new

A Proc object generated by proc ignores extra arguments.
proc {|a,b| [a,b] }.call(1,2,3) # output => [1,2]

A Proc object generated by proc provides nil for missing arguments.

proc {|a,b| [a,b] }.call(1) # output => [1,nil]

A Proc object generated by proc expands a single array argument.

proc {|a,b| [a,b] }.call([1,2]) # output => [1,2]

A Proc object generated by lambda doesn’t have such tricks.
It throw ArgumentError exception.

lambda {|a,b| [a,b] }.call(1,2,3) # output => ArgumentError
lambda {|a,b| [a,b] }.call(1) # output => ArgumentError
lambda {|a,b| [a,b] }.call([1,2]) # output => ArgumentError

=> the use of return in proc and lambda

lambda returns out of itself, and proc returns out of itself AND the function that called it. let us illustrate it.

def proc_return
  proc_obj = proc do 
    puts "Iam in Proc object created with proc"
    return "Hello"
  end
  puts proc_obj.call
  puts "How are you"
end

def lambda_return
  lambda_obj = lambda do 
    puts "Iam in Proc object created with lambda"
    return "Hello"
  end
  puts lambda_obj.call
  puts "How are you"
end

puts "output of proc_return"
proc_return

puts "output of lambda_return"
lambda_return

Now run the file to see the output

arun@arun-yadav:~$ ruby /home/arun/proc_demo.rb
output of proc_return
Iam in Proc object created with proc
output of lambda_return
Iam in Proc object created with lambda
Hello
How are you

So you can easily see that, when return called in a Proc object control immediately exit from the proc object as well as the method calling the proc object and so in out put no line after the return statement get printed. But you can see that lambda behave as expected, it return from proc object and other lines in the method get executed.

NOTE : proc is full of surprise. always use lambda to implement a Proc object

REFERENCE :

http://www.ruby-doc.org/core-2.0.0/Proc.html #ruby proc documentation

http://stackoverflow.com/questions/626/when-to-use-lambda-when-to-use-proc-new # comparison between Proc.new and lambda.