简体   繁体   中英

Ruby exercise - block to array

I'm playing Ruby game and got stuck at this :

Implement class Squirrel in a way below API will be supported.

 squirrel = Squirrel.new squirrel.fight do jump kick punch jump end squirrel.actions #=> ['jump', 'kick', 'punch', 'jump'] 

I was experimenting with def find(&block) and saving it as Proc later, but it probably shouldn't be done this way. I'll appreciate any hints.

I'll appreciate any hints

Sure. fight should accept a block and instance_eval it. jump , kick and others should be methods on the same class.

This is a rather standard metaprogramming technique that was popularized many years ago by the BlankSlate and XmlBase classes in Jim Weirich 's builder Gem.

The main idea is to create a "blank slate" object, ie an object that has no methods, and then record all method calls on this object.

Here is one possible implementation:

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

Try instance_eval . And/or read this this: Change the context/binding inside a block in ruby

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM