Reputation: 3552
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.
Upvotes: 3
Views: 4924
Reputation: 237110
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.)
Upvotes: 5