用args移动块的绑定

时间:2014-04-14 10:25:21

标签: ruby metaprogramming

我通过编写一个简单的DSL来学习ruby。 DSL用于支持事件源块。

class Coupon
    include AggregateRoot

    attr_reader :status

    on :CouponApprovedEvent do |event|
        #want to update @status of Coupon instance
        #but the binding is with Coupon class
        @status = 'APPROVED' 
    end

    #other instance methods of Coupon 
end

" on"优惠券映射的方法阻止给定事件,该事件用于重构聚合。它在模块AggregateRoot中定义:

module AggregateRoot

    attr_reader :events

    def handle event
        operation = self.class.event_handlers[event.class.name.to_sym]
        operation.call event
    end

    def self.included(clazz)
        clazz.class_eval do
            @event_handlers = {}

            def self.on event_clazz, &operation
                @event_handlers[event_clazz] = operation
            end

            def self.event_handlers
                @event_handlers
            end
        end
   end
end

但由于该块与优惠券类绑定,因此以下测试失败,因此它更新Coupon class.status而不是Coupon instance.status。

class CouponTest < MiniTest::Unit::TestCase
    def setup
       @id = 1
       @ar = Coupon.new(@id)
    end

    def test_reconsititute_aggregate_root
       @ar.handle(CouponApprovedEvent.new(@id))
       assert @ar.approved?
    end
end

所以我改变了这样的块调用来移动绑定:

module AggregateRoot

    def handle event
        operation = self.class.event_handlers[event.class.name.to_sym]
        instance_eval(&operation)
    end
end

在这种情况下,测试通过,但我找到了| event |参数丢失(优惠券实例被传递)。

有没有办法用args移动块的绑定?

1 个答案:

答案 0 :(得分:1)

尝试使用以下代码而不是operation.call event

instance_exec(event, &operation)