CSC/ECE 517 Fall 2007/wiki1b 2 Method Missing: Difference between revisions
Line 28: | Line 28: | ||
A normal approach to this would be to define 6 different methods in our code and let the sub classes use these 6 methods to access the search API. Now, lets see the downside of this approach. Suppose after a year, we decide to introduce new features to flickr API like tagging each photo by its location. To achieve this, a new attribute called "location" can be added to our database which would tell where that particular photo was taken. Now, to provide the functionality of "search by location" we will have to '''modify''' our Search API class, so that sub classes can use this new search method. | A normal approach to this would be to define 6 different methods in our code and let the sub classes use these 6 methods to access the search API. Now, lets see the downside of this approach. Suppose after a year, we decide to introduce new features to flickr API like tagging each photo by its location. To achieve this, a new attribute called "location" can be added to our database which would tell where that particular photo was taken. Now, to provide the functionality of "search by location" we will have to '''modify''' our Search API class, so that sub classes can use this new search method. | ||
Now, lets do it in a Ruby way! This can be achieved by Method Missing. Have a look at the following code and the | Now, lets do it in a Ruby way! This can be easily achieved by Method Missing. Have a look at the following code and the inlined comments: | ||
def method_missing(method_id, *arguments) | def method_missing(method_id, *arguments) | ||
Line 34: | Line 34: | ||
if match = /search_(by)_([_a-zA-Z]w*)/.match(method_id.to_s) | if match = /search_(by)_([_a-zA-Z]w*)/.match(method_id.to_s) | ||
# Extract the attribute names, for ex. tags, keywords etc | |||
attribute_names = extract_attribute_names_from_match(match) | |||
# Check if the attributes exist in the database, else call Method_missing method of Superclass | |||
super unless all_attributes_exists?(attribute_names) | |||
# Construct conditions from the attribute names and arguments | |||
# For different pair of attribute and argument, different conditions can be constructed. | |||
# For example, take a pair (keywords,Wolfpack), for which conditions like "keywords = 'Wolfpack'" or | |||
# "keywords LIKE '%Wolfpack%'" can be created. | |||
conditions = construct_conditions_from_arguments(attribute_names, arguments) | |||
# Create an array of conditions so that it can be passed around methods | |||
options = { :conditions => conditions } | options = { :conditions => conditions } | ||
# Execute the database query here and return the results | |||
else | else | ||
# If the called method is not of the type "search_by", call the method_missing of Parent Class | |||
super | super | ||
end | end | ||
end | end | ||
Revision as of 18:39, 1 October 2007
"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."
A world without "Method Missing"
What is "Method Missing" and what the fuss is all about ???
"Method Missing for Dummies" Example!
-> http://rubylearning.com/satishtalim/ruby_method_missing.html
Provide Extensive APIs with Method Missing!
@ http://ajax.stealthsettings.com/rubyisms-in-rails/metaprogramming/
This section covers how we can use Method Missing to provide a very comprehensive list of API methods in a class, with a little amount of code.
Lets assume that we are creating a flickr search API class. What could be the interface of this class? Well basically, the purpose of this class would be to provide a variety of methods using which developers can search photos in flickr database. For example, assume that our photo database has attributes like keywords, tags, user, content_type, free_photos and date for each photo. And we want to define the following methods in the Flickr Search API:
flickr.search_by_keywords("Wolfpack")
flickr.search_by_tags("Sports")
flickr.search_by_user("Vinay")
flickr.search_by_content_type("paintings")
flickr.search_by_free_photos("Million dollar Art")
flickr.search_by_date_added_on("10/1/2007")
A normal approach to this would be to define 6 different methods in our code and let the sub classes use these 6 methods to access the search API. Now, lets see the downside of this approach. Suppose after a year, we decide to introduce new features to flickr API like tagging each photo by its location. To achieve this, a new attribute called "location" can be added to our database which would tell where that particular photo was taken. Now, to provide the functionality of "search by location" we will have to modify our Search API class, so that sub classes can use this new search method.
Now, lets do it in a Ruby way! This can be easily achieved by Method Missing. Have a look at the following code and the inlined comments:
def method_missing(method_id, *arguments)
# Enter only if method called is of the type "search_by" if match = /search_(by)_([_a-zA-Z]w*)/.match(method_id.to_s) # Extract the attribute names, for ex. tags, keywords etc attribute_names = extract_attribute_names_from_match(match)
# Check if the attributes exist in the database, else call Method_missing method of Superclass super unless all_attributes_exists?(attribute_names)
# Construct conditions from the attribute names and arguments # For different pair of attribute and argument, different conditions can be constructed. # For example, take a pair (keywords,Wolfpack), for which conditions like "keywords = 'Wolfpack'" or # "keywords LIKE '%Wolfpack%'" can be created. conditions = construct_conditions_from_arguments(attribute_names, arguments) # Create an array of conditions so that it can be passed around methods options = { :conditions => conditions } # Execute the database query here and return the results else # If the called method is not of the type "search_by", call the method_missing of Parent Class super end
end
Creating Dynamic Methods on the Fly!
-> http://redhanded.hobix.com/inspect/hatchingNewMethodsInMidAir.html
Build your own DSL with Ruby!
-> http://liquiddevelopment.blogspot.com/2006/04/twisting-and-shaping-dsls-using-ruby.html , http://riffraff.blogsome.com/2006/05/02/metaprogramming-breakfast/