下面是如何包裝方法與一個校驗器的簡單示例:
class Foo
def foo(a, b, c)
p a, b, c
end
def bar(a, b)
p a, b
end
validate(:foo, :bar) {|*args, &blk| args.reduce(:+) == 6 }
end
Module#validate
該方法採用的方法名的列表,以及與這些方法中的驗證邏輯塊。
foo = Foo.new
foo.foo(1, 2, 3)
# 1
# 2
# 3
foo.bar(2, 4)
# 2
# 4
foo.foo(2, 3, 4)
# [2, 3, 4] (Validator::ValidationError)
foo.bar(2, 3)
# [2, 3] (Validator::ValidationError)
正如你所看到的,驗證拒絕在最後兩個調用參數列表,因爲他們沒有通過條件塊。
這是使所有事情都發生的「魔法」,這實際上並不是魔法。我們生成一個module
,它覆蓋了我們想驗證的方法,如果驗證失敗,那麼raise
是一個例外,然後簡單地調用super
。然後我們prepend
該模塊到我們當前所在的類/模塊,即調用validate
方法的模塊。基本上就是這樣。
我選擇也是個不錯的紅寶石公民,包裹在一個改進了整個事情,所以你需要說
using Validator
實際激活它。
module Validator
class ValidationError < ArgumentError; end
refine Module do
def validate(*methods, &validator)
prepend(Module.new do
methods.each do |method|
define_method(method) do |*args, &blk|
raise ValidationError, args.inspect unless yield *args
super(*args, &blk)
end
end
end)
end
end
end
您的問題不清楚。 「依靠班級或模塊」是什麼意思?你能編輯你的問題來包含示例代碼嗎? –
我想知道你爲什麼想在這裏使用裝飾模式。爲什麼不只是內聯驗證參數?這樣做大概有三條簡單線條。 –
真的不只是這種方法,我的軟件中還有其他方法可以使用這個裝飾器。 –