Include a module to define dynamic class method

class, module, ruby

Solution

You don't have to pass a string to `class_eval`. It can take a block instead. In fact, I can't think of a single occasion where I've had to pass a string to `class_eval`. So we can rewrite the ClassMethods module like so:

module ClassMethods
  def use_id_and_name_from_module(use_attribute)
    class_eval do 
      define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"}
    end
  end
end

But in this particular case, we're just telling `self` to `class_eval`, meaning we're already in that class's context. So it can actually be shortened to:

module ClassMethods
  def use_id_and_name_from_module(use_attribute)
    define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"}
  end
end

(I just wanted to show how `class_eval` really works, since you seemed most interested in that part.)

Problem

I'm playing around with Ruby and I have written the following code: ``` module IdAndNameRedefine def self.included(base) base.extend(ClassMethods) end module ClassMethods def use_id_and_name_from_module(use_attribute) class_eval <<CODE def id_and_name "\#{id}-\#{#{use_attribute}.downcase}" end CODE end end end class Model include IdAndNameRedefine attr_reader :id, :name1, :name2 def initialize(id, name1, name2) @id = id @name1 = name1 @name2 = name2 end def id_and_name "#{id}-#{name1}" end use_id_and_name_from_module :name2 end model = Model.new(1, "TesT", "Test number TWO") puts model.id_and_name ``` When I'm trying to do here is to override the class method `id_and_name` in class Model with a method dynamicly inserted by the `IdAndNameRedefine`-module. When that module is included, it creates a "static" method (really, a class method of the Model.class as I understands it) and when `use_id_and_name_from_module` is called, it creates a class method in Model which redefines the `id_and_name` to use whatever attribute of Model asked for. My question is.. Are there any better way of doing this, or is this the "correct" way of doing it? I'm not really sure if I like the class_eval with takes a string where I need to escape values etc. to make this work.

Original source