Meta programming
From Logic Wiki
Meta Programming can be defined as writing codes which writes codes.
Contents
Example 1
Look at the example below
class Account
attr_accessor :name, :address, :email, :notes, :bank_balance
end
user_info = {
:name => "Ali",
:address => "Timperley",
:email => "ali@iybar.com",
:notes => "good guy",
:bank_balance => 0
}
account = new Account.new
account.name - user_info[:name]
account.address = user_info[:address]
account.email = user_info[:email]
account_notes = user_info[:notes]
account_bank_balance = user_info[:bank_balance]
This is the classic way of creating a new user and fill the object. Take a look at it now
class Account
attr_accessor :name, :address, :email, :notes, :bank_balance
def assign_values(values)
values.each_key do |k|
self.send("#{k}=)", values[k])
end
end
user_info = {
:name => "Ali",
:address => "Timperley",
:email => "ali@iybar.com",
:notes => "good guy",
:bank_balance => 0
}
account = new Account.new
account.assign_values(user_info)
what happens here is in the self.send line we are saying something like this
self.send("#{k}=)", values[k])
| | |
V V V
self.name = values[k]
Example 2
class String
def self.add_new_method(name)
send(:define_method, name){
puts "You created a method named #{name}, and you are in it right now!"
}
end
end
String.add_new_method("Ali")
"string".Ali
here we used define_method method to create a method in a class. This newly on the fly created method writes some text. When we call it, it creates a method named Ali and this method writes a text. A bit complex huh ?
Example 3
class Array
def self.add_new_method(name, &logic)
Array.send(:define_method, name) do |*args|
locgic.call(self, *args)
end
end
Array.add_new_method("prepend_array") do |me, x|
me.each{ |e| puts "#{x} #{e} "}
end
["cat", "dog", "bird"].prepend_array("Animal:")
self and me in the codes above are necessary to make each aware of which object it's in
Example 4
class Model
@all_fields = []
def self.field(name)
@@all_fields << name
attr_accessor(name)
end
def initialize
@fields = @@all_fields
end
end
class Account < Model
field :balance
field :address
field :name
end
a = Account.new
a.balance = 1000000
a.address = "212 main St"
a.name = "Mr Who"
puts a.inspect