CSC/ECE 517 Fall 2007/wiki1b 2 c9: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
mNo edit summary
 
(4 intermediate revisions by the same user not shown)
Line 7: Line 7:
Ruby has a powerful way to intercept calls to undefined method. This is implemented by defining method_missing in our class definition. If a call is made to an undefined method on a object, Ruby passes the name of the method and its arguments to the method_missing.  This is an efficient and safest way to intercept calls made to unknown methods and handles them in a proper fashion.
Ruby has a powerful way to intercept calls to undefined method. This is implemented by defining method_missing in our class definition. If a call is made to an undefined method on a object, Ruby passes the name of the method and its arguments to the method_missing.  This is an efficient and safest way to intercept calls made to unknown methods and handles them in a proper fashion.
Let us look into few examples (Source: http://rubylearning.com/satishtalim/ruby_method_missing.html
Let us look into few examples (Source: http://rubylearning.com/satishtalim/ruby_method_missing.html
  class Dummy   
  '''class Dummy   
def method_missing(m, *args)   
  def method_missing(m, *args)   
puts "There's no method called #{m} here, please try again."   
    puts "There's no method called #{m} here, please try again."   
end   
  end   
  end   
  end'''  
Dummy.new.anything   
Dummy.new.anything   
>ruby tmp.rb   
>ruby tmp.rb   
Line 19: Line 19:
In the following example, method method_missing intercepts and prints out a message with method name and argument list (if any) and forwards on the method call using 'send' method without knowing anything about the object passed to it. (source: http://blog.mauricecodik.com/2005/12/more-ruby-methodmissing.html)
In the following example, method method_missing intercepts and prints out a message with method name and argument list (if any) and forwards on the method call using 'send' method without knowing anything about the object passed to it. (source: http://blog.mauricecodik.com/2005/12/more-ruby-methodmissing.html)


class SimpleCallLogger
  '''class SimpleCallLogger
  def initialize(o)
    def initialize(o)
    @obj = o
      @obj = o
  end
    end
  def method_missing(methodname, *args)
    def method_missing(methodname, *args)
    puts "called: #{methodname}(#{args})"
      puts "called: #{methodname}(#{args})"
    a = @obj.send(methodname, *args)
      a = @obj.send(methodname, *args)
    puts "\t-> returned: #{a}"
      puts "\t-> returned: #{a}"
    return a
      return a
  end
    end
end
  end'''


Another use of method_missing: (Source: http://redhanded.hobix.com/inspect/theBestOfMethod_missing.html)
Another use of method_missing: (Source: http://redhanded.hobix.com/inspect/theBestOfMethod_missing.html)


def method_missing(method)
  '''def method_missing(method)
    @posts = User.find_first(['username = ?', method.to_s]).posts
    @posts = User.find_first(['username = ?', method.to_s]).posts
    render_action 'index'     
    render_action 'index'     
    cache_page if ActionController::Base.perform_caching
    cache_page if ActionController::Base.perform_caching
end
  end'''


The above code is an example of a controller used for generating RSS and Atom Feeds to user.  It is used by Elite Journal which is a multi user. Since their web page changes display every now and then depending upon the status of user login. Therefore caching the output is very hard. Therefore, most of the time the output is not cached. So, generally the RSS and Atom Feeds are cached.  Since Elite Journal is multi-user, there is a feed for each user. This feed is combined with the method_missing call such that a call to the /rss/scott URL will retrieve the feed to the user “Scott”. In the above example, the page is cached if caching is enabled by the action controller.
The above code is an example of a controller used for generating RSS and Atom Feeds to user.  It is used by Elite Journal which is a multi user. Since their web page changes display every now and then depending upon the status of user login. Therefore caching the output is very hard. Therefore, most of the time the output is not cached. So, generally the RSS and Atom Feeds are cached.  Since Elite Journal is multi-user, there is a feed for each user. This feed is combined with the method_missing call such that a call to the /rss/scott URL will retrieve the feed to the user “Scott”. In the above example, the page is cached if caching is enabled by the action controller.
Another set of example for the use of method_missing is as follows: (Source: facets.rubyforge.org/src/lib/facets/core/kernel/as.rb)
Another set of example for the use of method_missing is as follows: (Source: facets.rubyforge.org/src/lib/facets/core/kernel/as.rb)
def method_missing(sym, *args, &blk)
  @ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
end
require 'rubygems'
require 'facets'


module James
  '''def method_missing(sym, *args, &blk)
  def name
    @ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
    "James"
    end
    require 'rubygems'
    require 'facets'
 
    module James
    def name
      "James"
    end
   end
   end
end


module Lynn
  module Lynn
  def name
    def name
    "Lynn"
      "Lynn"
    end
   end
   end
end


class FamilyMember
  class FamilyMember
  include James
    include James
  include Lynn
    include Lynn
end
  end'''


FamilyMember.ancestors # => [FamilyMember, Lynn, James, Object, Kernel]
FamilyMember.ancestors # => [FamilyMember, Lynn, James, Object, Kernel]
Line 71: Line 72:
In above example method_missing definition allows you to call a method on any ancestor. Initially instance of FamilyMember i.e member receives a message as which returns an instance of As. After returning the instance of As, member receives messae “name”. Since As does not contain the definition of name, the method_missing is called where in name is passed as an arguments. Within the method, instance_method is called on the ancestor with the name as the symbol. The instance_method will return the unbound method name since it is not defined. Then, method_missing binds the name to the subject which is member (instance of FamilyMember) and sends a call message along with the arguments passed before. Here, since name binds to the member, it can access the state or behavior of the member.
In above example method_missing definition allows you to call a method on any ancestor. Initially instance of FamilyMember i.e member receives a message as which returns an instance of As. After returning the instance of As, member receives messae “name”. Since As does not contain the definition of name, the method_missing is called where in name is passed as an arguments. Within the method, instance_method is called on the ancestor with the name as the symbol. The instance_method will return the unbound method name since it is not defined. Then, method_missing binds the name to the subject which is member (instance of FamilyMember) and sends a call message along with the arguments passed before. Here, since name binds to the member, it can access the state or behavior of the member.
Last example for the purpose of using method_missing. (source: http://services.tucows.com/developers/2007/08/03/rubys-method_missing-method-explained-with-lolcats/)
Last example for the purpose of using method_missing. (source: http://services.tucows.com/developers/2007/08/03/rubys-method_missing-method-explained-with-lolcats/)
class LolCat


   def confess
   '''class LolCat
    puts “I made you a cookie…but then I eated it.”
    def confess
  end
      puts “I made you a cookie…but then I eated it.”
    end


  def eat
    def eat
    puts “NOM NOM NOM.”
      puts “NOM NOM NOM.”
  end
     end
 
  def method_missing(method)
     puts “Oh noes! I has no idea how to #{method}.”
  end


end
    def method_missing(method)
      puts “Oh noes! I has no idea how to #{method}.”
    end
  end'''


> kitty = LolCat.new
> kitty = LolCat.new

Latest revision as of 01:44, 10 October 2007

CSC- 517 Object-Oriented Languages and Systems

                                     Wiki Assignment

Topic 2 : There are plenty of examples of method_missing on the Web. Unfortunately, I find most of them rather difficult to understand. One needs to look at quite a bit of source code and figure out what it does. Fix this by giving a plain-English description of several uses of method_missing not covered in our class, with Web links to the pages where you found them.


Ruby has a powerful way to intercept calls to undefined method. This is implemented by defining method_missing in our class definition. If a call is made to an undefined method on a object, Ruby passes the name of the method and its arguments to the method_missing. This is an efficient and safest way to intercept calls made to unknown methods and handles them in a proper fashion. Let us look into few examples (Source: http://rubylearning.com/satishtalim/ruby_method_missing.html

class Dummy  
  def method_missing(m, *args)   
    puts "There's no method called #{m} here, please try again."  
  end  
end  

Dummy.new.anything >ruby tmp.rb Output: There's no method called anything here, please try again. In the above example, a call is made to a method called anything on object of class Dummy. There is no method called “anything” defined within the class. Ruby passes the name “anything” to method_missing. Hence the above output is displayed.

In the following example, method method_missing intercepts and prints out a message with method name and argument list (if any) and forwards on the method call using 'send' method without knowing anything about the object passed to it. (source: http://blog.mauricecodik.com/2005/12/more-ruby-methodmissing.html)

 class SimpleCallLogger
   def initialize(o)
     @obj = o
   end
   def method_missing(methodname, *args)
     puts "called: #{methodname}(#{args})"
     a = @obj.send(methodname, *args)
     puts "\t-> returned: #{a}"
     return a
   end
 end

Another use of method_missing: (Source: http://redhanded.hobix.com/inspect/theBestOfMethod_missing.html)

  def method_missing(method)
    @posts = User.find_first(['username = ?', method.to_s]).posts
    render_action 'index'    
    cache_page if ActionController::Base.perform_caching
  end

The above code is an example of a controller used for generating RSS and Atom Feeds to user. It is used by Elite Journal which is a multi user. Since their web page changes display every now and then depending upon the status of user login. Therefore caching the output is very hard. Therefore, most of the time the output is not cached. So, generally the RSS and Atom Feeds are cached. Since Elite Journal is multi-user, there is a feed for each user. This feed is combined with the method_missing call such that a call to the /rss/scott URL will retrieve the feed to the user “Scott”. In the above example, the page is cached if caching is enabled by the action controller. Another set of example for the use of method_missing is as follows: (Source: facets.rubyforge.org/src/lib/facets/core/kernel/as.rb)

 def method_missing(sym, *args, &blk)
   @ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
   end
   require 'rubygems'
   require 'facets'
   module James
   def name
     "James"
   end
 end
 module Lynn
   def name
     "Lynn"
   end
 end
 class FamilyMember
   include James
   include Lynn
 end

FamilyMember.ancestors # => [FamilyMember, Lynn, James, Object, Kernel] member = FamilyMember.new member.name # => "Lynn" member.as(James).name # => "James"

In above example method_missing definition allows you to call a method on any ancestor. Initially instance of FamilyMember i.e member receives a message as which returns an instance of As. After returning the instance of As, member receives messae “name”. Since As does not contain the definition of name, the method_missing is called where in name is passed as an arguments. Within the method, instance_method is called on the ancestor with the name as the symbol. The instance_method will return the unbound method name since it is not defined. Then, method_missing binds the name to the subject which is member (instance of FamilyMember) and sends a call message along with the arguments passed before. Here, since name binds to the member, it can access the state or behavior of the member. Last example for the purpose of using method_missing. (source: http://services.tucows.com/developers/2007/08/03/rubys-method_missing-method-explained-with-lolcats/)

 class LolCat
   def confess
     puts “I made you a cookie…but then I eated it.”
   end
   def eat
     puts “NOM NOM NOM.”
   end
   def method_missing(method)
     puts “Oh noes! I has no idea how to #{method}.”
   end
 end

> kitty = LolCat.new => #<LolCat:0x349a40>

> kitty.confess I made you a cookie...but then I eated it. => nil

> kitty.eat NOM NOM NOM. => nil

> kitty.poop Oh noes! I has no idea how to poop. => nil

In the above example, we create an instance of LolCat which is named kitty. Next, call the method “confess” on kitty. Since it is defined , the method “confess” is called and appropriate result is printed. When the method poop is called, the method_missing is called since the method “poop” is not defined. Ruby passes the name of the method i.e “confess” and arguments that are needed to the method “poop”. The method_missing displays an error accordingly.