I am currently experimenting with Ruby and Rails, and I've hit a few sections in tutorials and books about metaprogramming. Many mention that it is an essential component of Ruby but they don't really go into detail. It's as if metaprogramming is the final frontier for Ruby programmers. Coming from a .NET background I am struggling to understand why it is supposedly so useful.
Metaprogramming is a technique by which you can write code that writes code by itself dynamically at runtime. This means you can define methods and classes during runtime.
Metaprogramming is a technique in which code operates on code rather than on data. It can be used to write programs that write code dynamically at run time. MetaProgramming gives Ruby the ability to open and modify classes, create methods on the fly and much more.
Ruby is known to have very powerful metaprogramming capabilities, that is, defining language structures (classes, modules, methods) at runtime. Unlike many other languages, Ruby's metaprogramming does not use special constructs different from “normal” programming, like macros, decorators or templates.
In Ruby a macro is like a method, just some code, that instead of returning a Ruby datatype returns more Ruby code! This code will get executed along with all the other code you have written when you run your program.
What benefits are gained when using metaprogramming?
You can create more expressive APIs than without it (for example ActiveRecord uses metaprogramming to define accessor methods based on a table's column names, so you can write things like person.age
instead of something like person.read_attribute("age")
, where person
is an active record object and the people
table has a column called age
) and you can accomplish some things with significantly less code than you otherwise would.
What is an eigenclass and how is it different from a singleton?
The terms "eigenclass" and "singleton class" are used interchangeably in the context of ruby.
In what situations is using metaprogramming common?
In situations where you'd otherwise have a lot of boiler plate code or when creating DSLs.
Example of use case 1:
Instead of writing something boiler-plate code like this:
class Foo
def bar
@bar
end
def bar=(b)
@bar = b
end
def baz
@baz
end
def baz=(b)
@baz = b
end
end
You can write this much shorter code using the metaprogramming method attr_accessor
, which automatically defines getter and setter methods with names based on the arguments you give it:
class Foo
attr_accessor :foo, :bar
end
If attr_accessor
didn't already exist in the standard library, you could define it yourself like this (to give you an idea what metaprogramming in ruby looks like):
class Module
def attr_accessor(*variable_names)
variable_names.each do |variable_name|
define_method( variable_name ) do
instance_variable_get( "@#{ variable_name }" )
end
define_method( "#{ variable_name }=" ) do |value|
instance_variable_set( "@#{ variable_name }", value)
end
end
end
end
What ethical implications are there around using code to modify the behaviour of other code, especially code which is not your own?
None.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With