柔軟な DSL を作成しようとしています。私はすでに DSL モジュールを持っていますmodule DSL
。DSL ユーザーは、これのスピンオフをクラスとして作成できます。DSL の主なポイントは、ユーザーがFeature
カスタム render メソッドでオブジェクトを作成できるようにすることです。をサポートする多くの醜い非 DRY コードFeature
があったため、抽象化されましたが、ユーザーはその機能がどのようにレンダリングされるかについて多くの制御を必要とし、私のメタプログラミングはそのタスクに対応していません。それがどのように設定されているかをお見せしましょう。
DSL は次のようになります。
module DSL
module ClassMethods
attr_accessor :features
def column(name, *args)
arguments = args.pop || {}
self.features = [] if self.features.nil?
self.features << Feature.new(name, arguments)
end
end
def self.included(base)
base.extend ClassMethods
end
end
end
その実装は次のようになります。
class DSLSpinOff
include DSL
feature :one
feature :two, render_with: :predefined_render
feature :three, render_with: :user_defined_render
feature :four, render_with: lambda {
puts "Go nuts, user!"
puts "Do as you please!"
}
def user_defined_render
#...
end
end
最後に、機能クラス自体は次のように DSL 内にあります。
module DSL
#...
private
class Feature
attr_accessor :name, :render_with
def initialize(name, *args)
self.name = name
attributes = args.pop || {}
# somehow delegate attributes[:render_with] to the render function, handling defaults, lamdbas, function string names, etc
self.render_with = attributes.fetch(:render_with, :default_render)
end
private
def default_render
#...
end
def predefined_render
#...
end
end
end