开发者

Dynamic Method Call within define_method

开发者 https://www.devze.com 2023-04-10 21:32 出处:网络
I\'m rather new to ruby, but am in a sit开发者_如何学编程uation where I have many repetitive methods. In attempting to DRY out my code I came up with something like the following:

I'm rather new to ruby, but am in a sit开发者_如何学编程uation where I have many repetitive methods. In attempting to DRY out my code I came up with something like the following:

class Foobar
  def some_method
    #
  end

  def some_method2
    #
  end

  def some_calculation
    #
  end

  [:some_method_test, :some_method2_test].each do |method|
    define_method method do
      return self.send(method.to_s.chomp "_test") / some_calculation
    end
  end
end

My question is regarding the .to_s.comp-- is there another way of writing this and accomplishing my goal?


Yes, you could start with the original name.

[:some_method, :some_method2].each do |method|
  define_method :"#{method}_test" do
    return self.send(method) / some_calculation
  end
end

Note that this kind of metaprogramming usually doesn't make much sense unless you have a very large number of trivial methods.


You could try to reduce the number of trivial methods. Maybe you could replace some_method, some_method2, some_method3 with generic_method(attribute_desired) where you'd call generic_method(1) instead of some_method, call generic_method(2) instead of some_method2, etc.

Sometimes testing can tell you something about the code that's being tested. If the testing is very boring, maybe it means the code being tested is too boring and has too much duplication.


And here is still another solution:

class Foobar
  # Non-test method definitions ...

  %w(some_method some_method2).each do |mthd|
    class_eval(<<-EOS, __FILE__, __LINE__ + 1)
      def #{mthd}_test
        #{mthd} / some_calculation
      end
    EOS
  end
end

In this way, the method definitions themselves are a bit slower, but they run much faster because they call no reflection method like send, and there stacktraces are shallower.

BTW, %w(foo bar) stands for words, and produces ['foo', 'bar'].

<<-EOS
  blah blah
  blah blah
EOS

is just a string that spreads multiple lines(HERE doc).

class_eval evaluates the string as a script, in the context of the current class(class Foobar). The __FILE__ and __LINE__ + 1 affect the file path and line number in the stacktrace.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号