Ruby is a dynamically typed language. You can define methods and classes at run time. Ruby has several metaprogramming styles.
One way is to use "define_method":
hello say hi
4$ for product bike charlotte
4$ for product bike rr
4$ for product bike not rr
Inside this code block, we are creating a new class with three methods. First method is not taking any parameter. Second method is taking two parameters. Third method is taking two parameters and last parameter is with the default value.
Another method for metaprogramming is using eval keyword. You can compile any string into a code. That is scary and somewhat crazy to me. It might be good for Artificial Intelligence projects, but not much useful for production application that you need to maintain and troubleshoot.
You can also define classes inside the loop and use that class outside or inside the loop.
hey world from Classtime2 printitagain objectid 18938904 classid 18939192
One way is to use "define_method":
Prints:
#defining new class c = Class.new c.class_eval do define_method :hi do puts "hello say hi" end define_method :get_price do |productname, location| puts "4$ for product #{productname} #{location}" end #method with default location define_method :get_price_2 do |productname, defaultlocation="rr"| puts "4$ for product #{productname} #{defaultlocation}" end end c.new.hi c.new.get_price("bike","charlotte") c.new.get_price_2("bike" ) c.new.get_price_2("bike","not rr" )
hello say hi
4$ for product bike charlotte
4$ for product bike rr
4$ for product bike not rr
Inside this code block, we are creating a new class with three methods. First method is not taking any parameter. Second method is taking two parameters. Third method is taking two parameters and last parameter is with the default value.
Another method for metaprogramming is using eval keyword. You can compile any string into a code. That is scary and somewhat crazy to me. It might be good for Artificial Intelligence projects, but not much useful for production application that you need to maintain and troubleshoot.
class MyClass eval %{def hi puts "Eval code string at runtime hello world" end } end d = MyClass.new d.hi
Prints:
Eval code string at runtime hello world
This code block is taking a string and running that. You can do similar code eval syntax in javascript and php as well.You can also define classes inside the loop and use that class outside or inside the loop.
2.times do class Classtimes puts "hello world from Class time objectid #{self.object_id} classid #{self.class.object_id} " end class Classtime2 def printit puts "hello world from Classtime2 printit objectid #{self.object_id} classid #{self.class.object_id} " end end Classtime2.new.printit end
Inside this code block, first class uses same object to print. Second class will create new objects for each iteration, but class will be defined once. Here is the output:
hey world from Class time objectid 18939288 classid 15445296
hey world from Classtime2 printit objectid 18939156 classid 18939192
hey world from Class time objectid 18939288 classid 15445296
hey world from Classtime2 printit objectid 18938988 classid 18939192
If you define the same class again outside of this loop, you may be wondering about the outcome. Ruby lets you extend the class,so it will use the same class to add method. It is similar to using partial keyword in C#, but you can have dynamic extensions with Ruby.
Output:#right after 2.times block code
class Classtime2 def printitagain puts "hey world from Classtime2 printitagain objectid #{self.object_id} classid #{self.class.object_id} " end end Classtime2.new.printitagain
hey world from Classtime2 printitagain objectid 18938904 classid 18939192
puts "you can look at instance methods and variables easily" p MyClass.new.instance_variables p MyClass.instance_methods(false) p Classtime2.instance_methods(false)Output:you can look at instance methods and variables easily [] [:hi] [:printit, :printitagain]
TODO for this subject:
Module extension
class << self
extending methods for single object