YAML has inheritance. The most clear example I have ever seen is here: http://blog.101ideas.cz/posts/dry-your-yaml-files.html
I need something more complex: I need to override object's object's property. Here is an example:
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
I want to get this result:
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
But if you declare like this, you will get these properties incorrect (according to expected values):
foo_database.server.ip -> will be None foo_database.user.name -> will be None
because new "server" object has only "port" property and it overrides whole old "server" object.
How do I get the kind of inheritance which I want to achieve?
Here is my exact intention with a working code in 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"}}
Unfortunately, you can't get the kind of "inheritance" you want to achieve because YAML's "inheritance" is more like a form of "merging hashes".
The <<: inserts the content of that node. Repeated nodes (objects) are first identified by an anchor (marked with the ampersand - “&”), and are then aliased (referenced with an asterisk - “*”) thereafter.
No, YAML does not include any kind of "import" or "include" statement. You could create a ! include <filename> handler.
In general the order of keys in a YAML file does not matter. Neither do blank lines. Indentation may be with any number of spaces, as long as it is consistent throughout the file.
Unfortunately, you can't get the kind of "inheritance" you want to achieve because YAML's "inheritance" is more like a form of "merging hashes".
Expanding out your configuration at the point you use the *default
alias, you have:
foo_database: server: ip: 192.168.1.5 port: 2000 db_name: test user: name: root password: root
If you use hashes with the same keys afterwards, they will completely overwrite the hashes declared earlier, leaving you with (excuse the formatting):
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
So, in your case, it would seem that since the config is not exactly the same, DRYing up your configuration using anchors and aliases probably isn't the right approach.
More references on this issue below:
If you really wanted to, I think you could reconfigure your YAML as below to get exactly what you want, but in your case, I would say the extra obfuscation isn't worth it:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With