ruby強力なdefine_method、閉める能力がある!
2368 ワード
閉パッケージの例は一般的にrubyのブロックについて話しています.スライスは、ローカル変数にアクセスし、実行コンテキストをバインドすることです(強力な2点).
最近mongoidのコードを見て、define_を発見しましたmethodは実行コンテキストをバインドすることもできます!
定義したgetterメソッドには、当時のmetadataクラスインスタンスがバインドされています.これにより、スタックシステムが関数の出入りパラメータを格納してくれるように、マッピングテーブルを追加する必要がなくなり、他のオブジェクトとの関係を維持できます.
簡単な説明方法を書きました.
出力:
"ss_car"# "embeds_one""ss_bus"# "ref_one"
nums = [10,3,22,34,17]
sum = 0
nums.each{|n| sum += n}
print sum
最近mongoidのコードを見て、define_を発見しましたmethodは実行コンテキストをバインドすることもできます!
def getter(name, metadata)
tap do
define_method(name) do |*args|
reload, variable = args.first, "@#{name}"
options = options(args)
if instance_variable_defined?(variable) && !reload
instance_variable_get(variable)
else
build(
name,
@attributes[metadata.key],
metadata,
options.merge(:binding => true, :eager => metadata.embedded?)
)
end
end
end
end
定義したgetterメソッドには、当時のmetadataクラスインスタンスがバインドされています.これにより、スタックシステムが関数の出入りパラメータを格納してくれるように、マッピングテーブルを追加する必要がなくなり、他のオブジェクトとの関係を維持できます.
簡単な説明方法を書きました.
class Metadata
attr_accessor :relation_name
end
module Accessor
def build(name, metadata)
p name, metadata, metadata.relation_name
end
module ClassMethods
def getter(name, metadata)
tap do
define_method(name) do
build(
name,
metadata
)
end
end
end
end
end
class Doc
include Accessor
extend Accessor::ClassMethods
end
meta = Metadata.new
meta.relation_name = 'embeds_one'
Doc.getter("ss_car", meta)
# p Doc.public_instance_methods
Doc.new.ss_car
meta2 = Metadata.new
meta2.relation_name = 'ref_one'
Doc.getter("ss_bus", meta2)
Doc.new.ss_bus
出力:
"ss_car"#