如何在Ruby中定义临时函数?

wswtfjt7  于 12个月前  发布在  Ruby
关注(0)|答案(2)|浏览(84)

我想避免为测试和其他情况编写重复的代码。
除了使用不方便的点调用语法test_parse_tag.(...)的lambda之外,还有更好的方法吗?

def test(name) = yield
def assert_equal(expected, actual) = p :tested

class El
  def self.parse_tag(s) = [:div, { class: 'some' }]
end

# I don't want to type `assert_equal El.parse_tag` every time
test 'El.parse_tag' do
  assert_equal El.parse_tag('span'),      [:span, {}]
  assert_equal El.parse_tag('#id'),       [:div,  { id: 'id' }]
  assert_equal El.parse_tag('div  a=b'),  [:div,  { a: 'b' }]
end

# So I use shortcut `test_parse_tag`
test 'El.parse_tag' do
  def test_parse_tag(actual, expected)
    assert_equal El.parse_tag(actual), expected
  end

  test_parse_tag 'span',      [:span, {}]
  test_parse_tag '#id',       [:div,  { id: 'id' }]
  test_parse_tag 'div  a=b',  [:div,  { a: 'b' }]
end

# PROBLEM, I don't want `test_parse_tag` to be available here
test_parse_tag 'span', [:span, {}]
mw3dktmi

mw3dktmi1#

您可以在预先创建的对象的上下文中执行传递给test的块。这里有一个使用instance_exec的简单版本,它将对象作为块参数传递沿着,以备需要:

def test(name, &block)
  obj = Object.new
  obj.instance_exec(obj, &block)
end

通过在对象内部执行块,方法在对象的单例类中定义,并且不会泄漏:

test 'one' do |context|
  def foo ; end

  defined? foo       #=> "method"
  context            #=> <Object:0x00007fd3b002c2f0>
  method(:foo).owner #=> #<Class:#<Object:0x00007fd3b002c2f0>>
end

test 'two' do |context|
  defined? foo       #=> nil
  context            #=> #<Object:0x00007fd3b0026fd0>
end

defined? foo #=> nil

RSpec将这种方法更进一步:每个示例组创建一个类,每个示例在该类的示例中进行评估,请参见A Word on Scope。

fcwjkofz

fcwjkofz2#

我认为最好在类中禁用测试,或者使用RSpec或minitest之类的库
对于您的架构结构,我建议使用lambda作为局部变量test_parse_tag。在test块之外将不可用

def test(name) = yield
def assert_equal(expected, actual) = p :tested

class El
  def self.parse_tag(s) = [:div, { class: 'some' }]
end

test 'El.parse_tag' do
  test_parse_tag = ->(actual, expected) { assert_equal El.parse_tag(actual), expected }

  test_parse_tag.('span', [:span, {}])
  test_parse_tag.('#id', [:div,  { id: 'id' }])
  test_parse_tag.('div  a=b', [:div,  { a: 'b' }])
end

相关问题