63

YAML には継承があります。私が今まで見た中で最も明確な例はここにあります: http://blog.101ideas.cz/posts/dry-your-yaml-files.html

もっと複雑なものが必要です。オブジェクトのオブジェクトのプロパティをオーバーライドする必要があります。次に例を示します。

database: &default
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

# database foo differs from default by only its port and user password
foo_database:
  <<: *default
  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root

私はこの結果を得たい:

foo_database.server.ip -> 192.168.1.5
foo_database.server.port -> 2001
foo_database.db_name -> foo
foo_database.user.name -> root
foo_database.user.password -> foo_root

しかし、このように宣言すると、これらのプロパティが正しくなくなります (期待値によると)。

foo_database.server.ip -> will be None
foo_database.user.name -> will be None

新しい「サーバー」オブジェクトには「ポート」プロパティしかなく、古い「サーバー」オブジェクト全体をオーバーライドするためです。

達成したい種類の継承を取得するにはどうすればよいですか?

編集

LiveScriptで動作するコードを使用した私の正確な意図はのとおりです。

config = 
  default: 
    ip: \192.168.1.5
    port: 2000
    name: \root 
    password: \root 
    db:
      name: \default
      location: \LA

  foo-database:~ -> @default `merge` do 
    ip: \11.11.11.11
    db:
      name: \my-foo 

  bar-database:~ -> @foo-database `merge` do 
    password: \1234 
    db:
      location: \SF

config.default 
# => {"ip":"192.168.1.5","port":2000,"name":"root","password":"root","db":{"name":"default","location":"LA"}}
config.foo-database  
# => {"ip":"11.11.11.11","port":2000,"name":"root","password":"root","db":{"name":"my-foo","location":"LA"}}
config.bar-database  
# => {"ip":"11.11.11.11","port":2000,"name":"root","password":"1234","db":{"name":"my-foo","location":"SF"}}
4

3 に答える 3

50

残念ながら、YAMLの「継承」は「ハッシュのマージ」の形式に似ているため、達成したい種類の「継承」を取得することはできません。

*defaultエイリアスを使用する時点で構成を拡張すると、次のようになります。

foo_database:
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

後で同じキーでハッシュを使用すると、前に宣言されたハッシュが完全に上書きされ、次のようになります(フォーマットを失礼します)。

foo_database:

  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
   name: root
   password: root  

  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root

したがって、あなたの場合、構成は完全に同じではないため、アンカーとエイリアスを使用して構成を乾燥させることは、おそらく適切なアプローチではないように思われます。

以下のこの問題に関するその他の参考資料:

編集

本当に必要な場合は、YAMLを以下のように再構成して、必要なものを正確に取得できると思いますが、あなたの場合、余分な難読化は価​​値がないと思います。

server_defaults: &server_defaults
  ip: 192.168.1.5
  port: 2000

user_defaults: &user_defaults
  name: root
  password: root

database: &default
  server:
    <<: *server_defaults
  db_name: test
  user: 
    <<: *user_defaults

foo_database:
  <<: *default
  server:
    <<: *server_defaults
    port: 2001
  db_name: foo
  user:
    <<: *user_defaults
    password: foo_root
于 2013-01-06T23:36:25.143 に答える