3

「method_missing」を使用してタグをフォーマットしようとしています。必要な結果を以下に示します。

<foo>\n
    <bar>\n
        <ab/>\n
    </bar>\n
</foo>\n

実行中のインデックスが必要だと思いますが、どこに配置するのが最適か、それが最善のアプローチかどうかは不明です。インデントを追加するにはどうすればよいですか?

def method_missing(meth, *args, &block)
    if args.length > 0
        my_other_method(args)
    else
        my_method(meth.to_s, &block)
    end
end

def my_other_method(args)
    "<#{args}/>"
end

def my_method(meth)     
    s = "<#{meth}>\n"
    s << "#{_indentation}"
    s << yield.to_s << "\n"
    s << "#{_indentation}"
    s << "</#{meth}>\n"
end

def _indentation
    ("--" * _level.to_i)    # dashes added to more easily infer spacing
end

def _level
    caller.rindex {|val| val.scan('my_method')} / 3
end

p foo{bar{baz(:a => "b"){}}}

私はこの間違った出力を取得します(余分な \n の原因は不明です)

<foo>\n
--<bar>\n
----<ab>\n
----</bar>\n
\n
--</foo>\n
4

1 に答える 1

1

コール スタックを使用して、インデントのレベルを取得できます。caller私のコードを参照してください。また、いくつかのクラスにコードを分離して、より多くのタグを使用できるようにすることもお勧めします。これは、多くのメソッドが定義されている可能性があるためmain です。

class TagFormatter
  def method_missing(method_name, *args, &block)
    _tagify method_name, args, &block
  end

  def _tagify(tag_name, args)
    if block_given?
      s = "#{_indentation}<#{tag_name}#{_attrs args}>\n"
      s << (yield || "")
      s << "#{_indentation}</#{tag_name}>\n"
    else
      "#{_indentation}<#{tag_name}#{_attrs args}/>\n"
    end
  end

  def _indentation
    "    " * _level
  end

  def _level
    caller.index { |val| val =~ /instance_eval/ } / 3 - 1
  end

  def _attrs(args)
    args.map { |arg| _to_attr arg }.join if args
  end

  def _to_attr(arg)
    if arg.kind_of? Hash
      arg.map { |k, v| %Q{ #{k}="#{v}"}}
    else
      %Q{ #{arg.to_s}}
    end
  end
end

例:

> tf = TagFormatter.new
> puts tf.instance_eval 'foo{bar{baz(:a => "b"){}}}'
<foo>
    <bar>
        <baz a="b">
        </baz>
    </bar>
</foo>
> puts tf.instance_eval 'foo{bar{baz(:a => "b")}}' # no block given in baz
<foo>
    <bar>
        <baz a="b"/>
    </bar>
</foo>
> puts tf.instance_eval 'foo{bar{baz("disabled", :readonly, :a=>"b")}}'
<foo>
    <bar>
        <baz disabled readonly a="b"/>
    </bar>
</foo>
于 2013-06-12T12:03:34.087 に答える