In the following code, the module is extended which means the method hash_initialized is treated as a class method, or an instance method of the eigen class. This is what we need since hash_initialized is called in the context of the eigen class.
What i don't understand is if the context for the module is the eigen class, then define_method should create a instance method called "initialize" of the eigen class, or in other words, a class method of class Cheese. Don't we need an instance method "initialize" here?
module HashInitialized
  def hash_initialized(*fields)
    define_method(:initialize) do |h|
        missing = fields - h.keys
      raise Exception, "Not all fields set: #{missing}" if missing.any?
      h.each do |k,v|
        instance_variable_set("@#{k}", v) if fields.include?(k) 
      end
    end
  end
end
class Cheese
  extend HashInitialized
  attr_accessor :color, :odor, :taste
  hash_initialized :color, :odor, :taste
end
				
                        
When you encounter seeming conundrums such as this one, try salting your code with
puts selfstatements:As you see,
selfis the classCheese, notCheese's singleton_class. Hence, the receiver for Module#define_method isCheese, so the method obligingly creates the instance methodinitializeonCheese.initializeis not among the instance methods created onCheesebecause I modified the code slightly to make it a private method:I also slightly altered the code that assigns values to the instance variables, and made the type of exception more specific.
If appropriate, you could change your argument test to:
You may wish to have
initializecreate the assessors: