Un héritage plus complexe à YAML?

YAML a un héritage. L'exemple le plus flagrant que j'ai jamais vu, c'est ici: http://blog.101ideas.cz/posts/dry-your-yaml-files.html

j'ai besoin de quelque chose de plus complexe: j'ai besoin de remplacer l'objet de propriété de l'objet. Voici un exemple:

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

je veux obtenir ce résultat:

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

mais si vous déclarez comme ceci, vous obtiendrez ces propriétés incorrectes (selon les valeurs attendues):

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

parce que de nouveaux l'objet " server "n'a que la propriété" port "et il l'emporte sur l'objet" server " tout entier.

Comment puis-je obtenir le genre d'héritage que je veux atteindre?

39
demandé sur Jauco 2013-01-06 21:54:22

2 réponses

malheureusement, vous ne pouvez pas obtenir le genre d ' "héritage" que vous voulez obtenir parce que l ' "héritage" de YAML est plus comme une forme de "fusion de hachures".

étendre votre configuration au point où vous utilisez le *default alias, vous avez:

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

si vous utilisez des hashes avec les mêmes clés par la suite, ils seront complètement remplacer les hachages déclaré plus tôt, vous laissant avec (excusez le mise en forme):

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

Donc, dans votre cas, il semblerait que, depuis la config n'est pas exactement la même chose, assécher votre configuration en utilisant des ancres et des alias n'est probablement pas la bonne approche.

Plus de références sur cette question ci-dessous:

Modifier

Si tu le voulais vraiment, je pense que vous pouvez reconfigurer votre YAML comme ci-dessous pour obtenir exactement ce que vous voulez, mais dans votre cas, je dirais que le supplément de dissimulation n'est pas la peine:

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
28
répondu Paul Fioravanti 2013-01-06 23:58:51

Que Diriez-vous de ceci? Utilisez plusieurs ancres.

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

foo_database:
  <<: *default
  server:
    << : *server
    port: 2001
  db_name: foo
  user:
    << : *user
    password: foo_root

C'est juste un peu de travail supplémentaire, et un peu plus difficile à lire que si ce que vous vouliez était intégré dans YAML comme vous l'avez suggéré (je pensais que cela fonctionnerait de cette façon aussi). Mais dans l'ensemble c'est pas mal.

7
répondu Tyler Collier 2014-02-25 19:47:23