I have some methods in a class that look like this:
def h_coil(chan)
raise NoDataError if @h_coils[chan].nil? @h_coils[chan]
end
def i_coil(chan)
raise NoDataError if @i_coils[chan].nil? @i_coils[chan]
end
and so on and so forth…
I’ve been refactoring a bit to cut down on the redunancy in the code,
and
I’m wondering your thoughts on the best way of doing this, considering
that all methods have the same “signature”.
Is define_method the smartest way?
pseudo code off the top of my head, probably has errors:
def create_coil_method(name)
define_method(name) do |chan|
iv = ("@" + name.to_s + “s”).to_sym
val = instance_variable_get(iv)
raise NoDataError if val.nil?
val[chan]
end
end
I’ve been refactoring a bit to cut down on the redunancy in the code,
and I’m wondering your thoughts on the best way of doing this,
considering that all methods have the same “signature”.
Is define_method the smartest way?
You are recreating functionality that’s already there (assuming coils
collections are arrays or hashes):
h={1=>2}
=> {1=>2}
h.fetch 1
=> 2
h.fetch 2
IndexError: key not found
from (irb):7:in `fetch’
from (irb):7
from :0
a=[1]
=> [1]
a.fetch 0
=> 1
a.fetch 1
IndexError: index 1 out of array
from (irb):16:in `fetch’
from (irb):16
from :0
IMHO it’s not worth while to use meta programming in this case but YMMV. If you use meta programming then I’d probably use a way that makes
sure
the member is there, properly initialized and the getter defined. I’d
probably create a module whose initialize will create member variables
and
which when included will define the create_coil for the including
class…
you can certainly use metaprogramming here, but you could accomplish the
same
effect with far less code:
My issue is that I’ve got other methods in the class that use these
particular instance variables, and instead of refactoring all of them in
one fell swoop I’m trying to go in smaller chunks. Mostly because I’m
working on the “production” system (long story), so if break anything I
need to be able to roll it back quickly.
then something like
class Coil
class Error < StandardError; end
class << self
def coil_attr *list
list.flatten.each do |a|
module_eval <<-code
def #{ a }_coil chan
@#{ a }_coil[chan] or raise Error, "chan=\#{ chan }"
end
code
end
end
end
coil_attr %w( a b c x y z )
you can certainly use metaprogramming here, but you could accomplish the
same
effect with far less code:
My issue is that I’ve got other methods in the class that use these
particular instance variables, and instead of refactoring all of them in
one fell swoop I’m trying to go in smaller chunks. Mostly because I’m
working on the “production” system (long story), so if break anything I
need to be able to roll it back quickly.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.