Ruby练习 - 阻止数组

时间:2016-08-30 07:33:42

标签: ruby

我正在玩Ruby游戏并且陷入困境:

  

支持以低于API的方式实施类Squirrel

squirrel = Squirrel.new
squirrel.fight do
  jump
  kick
  punch
  jump
end

squirrel.actions #=> ['jump', 'kick', 'punch', 'jump']

我正在试验def find(&block)并稍后将其保存为Proc,但它可能不应该以这种方式完成。我会感激任何提示。

3 个答案:

答案 0 :(得分:2)

  

我会感激任何提示

不确定。 fight应该接受一个阻止并instance_evaljumpkick和其他人应该是同一个班级的方法。

答案 1 :(得分:1)

这是一种相当标准的元编程技术,多年前由BlankSlateXmlBase宝石中的Jim Weirichbuilder类推广。

主要思想是创建一个“空白平板”对象,即没有方法的对象,然后在该对象上记录所有方法调用。

以下是一种可能的实施方式:

class Squirrel
  class Recorder < BasicObject
    (instance_methods + private_instance_methods).each(&method(:undef_method))
    def method_missing(method) @actions << method.to_s end
  end

  attr_reader :actions, :recorder

  private
  attr_writer :actions, :recorder

  def initialize
    self.actions = []
    self.recorder = Recorder.allocate
    Object.public_instance_method(:instance_variable_set).bind(recorder).(:@actions, actions)
  end

  public def fight(&block)
    BasicObject.public_instance_method(:instance_eval).bind(recorder).(&block)
  end
end

require 'minitest/autorun'
describe Squirrel do
  before do @squirrel = Squirrel.new end

  describe '#fight' do
    it 'should record its actions' do
      @squirrel.fight do              jump; kick; punch; jump end
      @squirrel.actions.must_equal %w[jump  kick  punch  jump]
    end
  end
end

答案 2 :(得分:0)

试试instance_eval。和/或读这个: Change the context/binding inside a block in ruby