YAMLはコンピュータで読み込め人にも優しい形式ですが、最下層だけでもインライン形式で書き出してくれれば、さらに読みやすくなるように思いますので、その方法を紹介します。
その1
Psychのソースコードを読む限り対象クラスにencode_withメソッドを追加することでYAMLの出力を変えることができます。それを利用した方法です。
Hashクラスの場合
Hashクラスの場合をはじめに説明します。
基本的には、対象とするクラスにencode_withメソッドを追加するだけです。
最下位の要素だけをインライン形式にしたいので、全ての要素の値がNumericかStringである場合だけを対象にしています。
yaml1.rb
require 'yaml'
class Hash
def encode_with(coder)
if self.all?{|k, v| Numeric===v or String===v}
coder.style = Psych::Nodes::Mapping::FLOW
end
coder.tag = nil
coder.map = self
end
end
puts [{"a"=>2, "b"=>3}, {"c"=>4}].to_yaml
# 出力結果
# ---
# - {a: 2, b: 3}
# - {c: 4}
Arrayクラスでは
Hashと同じようにしてもインライン形式で出力してくれませんでしたので、ここではemit_coderメソッドをオーバーライドしています。とは言ってもwhen :seqの次の1行を変更しているだけです。
おそらくPsychのバグではないかと思います。
yaml2.rb
require 'yaml'
module Psych
module Visitors
class YAMLTree < Psych::Visitors::Visitor
alias_method :emit_coder_orig, :emit_coder
def emit_coder c, o
case c.type
when :seq
@emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
c.seq.each do |thing|
accept thing
end
@emitter.end_sequence
else
emit_coder_orig c, o
end
end
end
end
end
class Array
def encode_with(coder)
if self.all?{|c| Numeric===c or String===c}
coder.style = Psych::Nodes::Mapping::FLOW
end
coder.tag = nil
coder.seq = self
end
end
puts ({"a"=>[1,2,3], "b"=>[4,5]}).to_yaml
# 出力
# ---
# a: [1, 2, 3]
# b: [4, 5]
その2
(2018.5.19追記)
acceptをオーバーライドして強引?にインライン出力する方法です。
YAMLStyle.flow_style()の中にインライン出力したいオブジェクトを入れることで、そのオブジェクトIDを登録し、YAML展開するときにstyleをFLOWに書き換えています。
こちらの方が出力の自由度は高いです。
yaml3.rb
require "yaml"
class YAMLStyle
@@flow_style_ids=[]
def self.flow_style(obj)
@@flow_style_ids << obj.__id__
obj
end
end
module Psych
module Visitors
class YAMLTree < Psych::Visitors::Visitor
alias_method :accept_orig, :accept
def accept target
acpt=accept_orig target
acpt.style=Psych::Nodes::Sequence::FLOW if YAMLStyle.class_variable_get(:@@flow_style_ids).include?(target.__id__)
acpt
end
end
end
end
puts [YAMLStyle.flow_style({"a"=>2, "b"=>3}), YAMLStyle.flow_style({"c"=>4})].to_yaml
puts ({"a"=>YAMLStyle.flow_style([1,2,3]), "b"=>YAMLStyle.flow_style([4,5])}).to_yaml
# 出力
# ---
# - {a: 2, b: 3}
# - {c: 4}
# ---
# a: [1, 2, 3]
# b: [4, 5]
使用したrubyのバージョンは2.5.1p57です。