DEV Community

Cover image for What is Metaprogramming?
Danny Rivera
Danny Rivera

Posted on

What is Metaprogramming?

Concept: Metaprogramming is writing programs that write programs! Sounds awesome right? Let's understand why metaprogramming is important. Take a look at the following code:

class Cryptocurrency
  attr_accessor :name, :symbol, :current_price, :last_updated, :price_change_24h  

  def initialize(name:, symbol:, current_price:, last_updated:, price_change_24h:)
    @name = name
    @symbol = symbol
    @current_price = current_price
    @last_updated = last_updated
    @price_change_24h = price_change_24h
  end
end 
Enter fullscreen mode Exit fullscreen mode

In this situation I have a Cryptocurrency class that initializes with a hash of attributes from CoinGecko's API and it works just fine. But what if they decide to change its API, we wouldn't be able to even create Cryptocurrency objects and our app will crash.
Luckily there's a solution for this problem, but first let's take a look at the send method. We can use it and simplify our code above with less code.

class Cryptocurrency
  attr_accessor :name, :symbol, :current_price, :last_updated, :price_change_24h  

  def initialize(crypto_hash)
    crypto_hash.each do |key, value|
      self.send("#{key}=", value)
    end
  end
end 
Enter fullscreen mode Exit fullscreen mode

What is going on here?

self.send("#{key}=", value)
Enter fullscreen mode Exit fullscreen mode

As we loop through each key value pair in our hash we use “message passing” to “send” a method to “self”.
How send method would look a like:

self.name = value
self.name = "Bitcoin"
Enter fullscreen mode Exit fullscreen mode

Now that we understand send, we can get into dynamically setting getters and setters. Let's first remember that attr_accessor is a class method just like attr_reader and attr_writer. So we can dynamically add getters or setters:

class Cryptocurrency
  def initialize(hash)
    crypto_hash.each do |key, value|
      self.class.attr_accessor(key)
      self.send("#{key}=", value)
    end
  end
end 
Enter fullscreen mode Exit fullscreen mode

By using Metaprogramming we can now get and set every attribute on an object instantiated from the Cryptocurrency class.

Reference:
Mass Assignment and Class Initialization

Top comments (0)