【yaml】.ymlファイルの使い方まとめ。&, *, <<の使い方


Dockerのdocker-compose.ymlやRuby on Railsのdatabase.yml、webpacker.ymlなどいくつかのファイルで使われている書式。

基本構文や&(アンカー), *(エイリアス), <<(インジェクト)の使い方について。

慣れるとコード量が少なく、便利な機能もありとても使いやすい。

目次

  1. yamlとは?
  2. yamlの使い方ポイント
  3. オブジェクト(ハッシュ)の使い方
  4. 配列の使い方
  5. 配列とオブジェクト(ハッシュ)の組み合わせ
  6. &(アンカー)と*(エイリアス)の使い方
  7. <<(インジェクト)の使い方
  8. コメントアウト
  9. nullの明示
  10. docker-compose.ymlのコンパイル例
  11. database.ymlのコンパイル例
  12. webpack.ymlのコンパイル例


yamlとは?

ヤムルと呼ぶ。XMLやJSONと同じようにデータ受け渡しのための書式。記述量が少なく軽量なので、使われる場面が増えている。

yamlからXMLやJSONにコンパイルすることもできる。変換は以下サイトが便利。


yamlの使い方ポイント

  • 拡張子は.yml(.yamlでもいい)
  • オブジェクトを表す{ }を使わない
  • カンマ,を使わない
  • 配列は[ ]を使わない。-で表す。
  • 文字列に" "' ')を使わなくていい。
  • 変数の代わりに、&(アンカー)を使う。
  • 変数の呼び出しは*(エイリアス) と <<(インジェクト)

よく目にする、{ }, [ ], ,, " "を使わないのでデータ量を少なくできる。


オブジェクト(ハッシュ)の使い方

配列はKey-Value方式。(他の言語と同じ。PHPだと連想配列、rubyだとハッシュ, jsだとオブジェクト)

.yml
name: yamada
gender: male
age: 27

↓ コンパイル

.json
{
    "name": "yamada",
    "gender": "male",
    "age": 27
}

シンプル。


入れ子のオブジェクト

インデントを使うと入れ子にできる。

.yml
yamada: 
    gender: male
    age: 27

↓ コンパイル

.json
{
    "yamada": {
        "gender": "male",
        "age": 27
    }
}


入れ子で複数のオブジェクト

.yml
yamada: 
    gender: male
    age: 27
tnaka: 
    gender: female
    age: 23

↓ コンパイル

.json
{
    "yamada": {
        "gender": "male",
        "age": 27
    },
    "tnaka": {
        "gender": "female",
        "age": 23
    }
}

データ量が増えれば増えるほど、ヤムルの方がシンプルなのがわかりやすい。


配列の使い方

配列は冒頭に-をつける。

.yml
- a
- b

↓ コンパイル

.json
[ "a", "b" ]


入れ子の配列

入れ子にする場合は、値のない-で改行し、インデントをつけて記述する。

.yml
- a
- 
    - b

↓ コンパイル

.json
[ "a", [ "b" ] ]

空の-が出てきたらネストしているということ。

▼例2

.yml
- a
- 
    - b
    - c
- c
- d
-
    - f
    -
        - g

↓ コンパイル

.json
[ "a", [ "b", "c" ], "c", "d", [ "f", [ "g" ] ] ]

どの要素の次元が揃っているかが一目でわかる。


配列とオブジェクト(ハッシュ)の組み合わせ

配列の中にオブジェクト(ハッシュ)をいれる

-の後ろにKVを記述する。

.yml
- a: 1
- b: 2

↓ コンパイル

.json
[ { "a": 1 }, { "b": 2 } ]



▼例2

.yml
- a: 1
- b: 2
- 3
-
    - 4
    - 5
    - c :6

↓ コンパイル

.json
[ { "a": 1 }, { "b": 2 }, 3, [ 4, 5, "c :6" ] ]


オブジェクト(ハッシュ)の中に配列をいれる

KVのvalueの部分を改行して-で記述する。インデントはしてもしなくても同じ。

インデントをつかた方がネストの関係が見やすい。

.yml
a: 
    - 1
    - 2

↓ コンパイル

.json
{ "a": [1, 2] ] }



▼インデントをつけない場合

.yml
a: 
- 1
- 2

↓ コンパイル

.json
{ "a": [1, 2] ] }


オブジェクト(ハッシュ)の中にオブジェクトの配列をいれる

.yml
a:
 - b: 1
 - d: 2

↓ コンパイル

.json
{ "a": [ { "b": 1 }, { "d": 2 } ] }


&(アンカー)と*(エイリアス)の使い方

変数のような機能。&(アンカー)と*(エイリアス)を使うことで、事前に定義したデータを使いわますことができる。

・命名: &アンカー名 値
・呼び出し: *アンカー名

単一データの場合

.yml
a: 
    - &x 1
    - *x

↓ コンパイル

.json
{ "a": [ 1, 1 ] }

&x 1でアンカー名xに1を代入。*xで呼び出している。



▼例2

.yml
- &x a:1
- *x

↓ コンパイル

.json
[ "a": 1, "a": 1 ]



▼例3

.yml
a:  
    - &x 1
    - 2
b:  
    - 3
    - *x

↓ コンパイル

.json
{ "a": [ 1, 2 ], "b": [ 3, 1 ] }


複数データの場合

オブジェクト(ハッシュ)の値にアンカーを使う。

キー名: &アンカー名

.yml
a: &x
    - 1
    - 2
b: *x

↓ コンパイル

.json
{ "a": [ 1, 2 ], "b": [ 1, 2 ] }


<<(インジェクト)の使い方

&(アンカー)と*(エイリアス)と合わせて使う。

エイリアスのデータを同じ次元で呼び出したい時に使う。(エイリアスで呼び出すと、ひとまとまりのデータとして呼び出され次元が一つ下がるため)

使えるのはオブジェクト(ハッシュ)で配列には使えない。

▼エイリアスのみの場合

.yml
a: &x
  b: 1
  c: 2

d: *x

↓ コンパイル

.json
{ "a": { "b": 1, "c": 2 }, "b": { "b": 1, "c": 2 } }

エイリアスで{ "b": 1, "c": 2 }を一塊で呼び出している。例えばこの一塊を活用して{ "b": 1, "c": 2, "d": 3 }のように同じ次元に追加したい場合に<<を使う。



<<インジェクトを使った場合

<<: *エイリアス名

.yml
a: &x
  b: 1
  c: 2

d: 
  <<: *x
  d: 3

↓ コンパイル

.json
{ "a": { "b": 1, "c": 2 }, "b": { "b": 1, "c": 2, "d": 3 } }



▼エラー1
<<を使わずに呼び出そうとするとエラーになる。

.yml
a: &x
  b: 1
  c: 2

d: 
  *x
  d: 3

↓ コンパイル

.json(エラー)
Error : Unable to parse.
Line : 6  *x



▼エラー2
配列には使えない。

.yml
a: &x
  - 1
  - 2

d: 
  <<: *x
  - 3

↓ コンパイル

.json(エラー)
Error : You cannot define a sequence item when in a mapping
Line : undefined  undefined


コメントアウト

コメントアウトは#を使う。コンパイルするとコメントアウトは無視される。

.yml
#コメントアウト
a: &x
  #bを定義
  b: 1
  #cを定義
  c: 2

d: *x

↓ コンパイル

.json
{ "a": { "b": 1, "c": 2 }, "b": { "b": 1, "c": 2 } }


nullの明示

KVで値を指定しない場合はnullになる。~を使うと明示的にnullを示せる。

.yml
a: 
b: ~

c: 
    - d:
    - e: ~

↓ コンパイル

.json
{ "a": null, "b": null, "c": [ { "d": null }, { "e": null } ] }


docker-compose.ymlのコンパイル例

docker-compose.ymlをjsonに変換するとどのように表示されるかの例。

docker-compose.yml
version: "3"
services:
  db:
    image: postgres:11.1-alpine
  web:
    build: .
    command: bin/rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    depends_on:
      - db

↓ コンパイル

.json
{
    "version": "3",
    "services": {
        "db": {
            "image": "postgres:11.1-alpine"
        },
        "web": {
            "build": ".",
            "command": "bin/rails s -p 3000 -b '0.0.0.0'",
            "volumes": [
                ".:/usr/src/app"
            ],
            "ports": [
                "3000:3000"
            ],
            "depends_on": [
                "db"
            ]
        }
    }
}


database.ymlのコンパイル例

database.ymlをjsonに変換するとどのように表示されるかの例。

database.yml
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On macOS with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On macOS with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: rails6_docker_alpine_development

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user running Rails.
  #username: rails6_docker_alpine

  # The password associated with the postgres role (username).
  #password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  #host: localhost

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  #port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: rails6_docker_alpine_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV['MY_APP_DATABASE_URL'] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: rails6_docker_alpine_production
  username: rails6_docker_alpine
  password: <%= ENV['RAILS6_DOCKER_ALPINE_DATABASE_PASSWORD'] %>

↓ コンパイル

.json
{
    "default": {
        "adapter": "postgresql",
        "encoding": "unicode",
        "pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>"
    },
    "development": {
        "adapter": "postgresql",
        "encoding": "unicode",
        "pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
        "database": "rails6_docker_alpine_development"
    },
    "test": {
        "adapter": "postgresql",
        "encoding": "unicode",
        "pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
        "database": "rails6_docker_alpine_test"
    },
    "production": {
        "adapter": "postgresql",
        "encoding": "unicode",
        "pool": "<%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>",
        "database": "rails6_docker_alpine_production",
        "username": "rails6_docker_alpine",
        "password": "<%= ENV['RAILS6_DOCKER_ALPINE_DATABASE_PASSWORD'] %>"
    }
}

コメントアウトが多いのでデータ量が多く感じるが、実際はそれほど多くない。

&default<<: *defaultで共通部として呼び出されている。

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>


webpack.ymlのコンパイル例

webpack.ymlをjsonに変換するとどのように表示されるかの例。

webpack.yml
# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  webpack_compile_output: true

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  additional_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

↓ コンパイル

.json
{
    "default": {
        "source_path": "app/javascript",
        "source_entry_path": "packs",
        "public_root_path": "public",
        "public_output_path": "packs",
        "cache_path": "tmp/cache/webpacker",
        "webpack_compile_output": true,
        "additional_paths": [],
        "cache_manifest": false,
        "extract_css": false,
        "static_assets_extensions": [
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".tiff",
            ".ico",
            ".svg",
            ".eot",
            ".otf",
            ".ttf",
            ".woff",
            ".woff2"
        ],
        "extensions": [
            ".mjs",
            ".js",
            ".sass",
            ".scss",
            ".css",
            ".module.sass",
            ".module.scss",
            ".module.css",
            ".png",
            ".svg",
            ".gif",
            ".jpeg",
            ".jpg"
        ]
    },
    "development": {
        "source_path": "app/javascript",
        "source_entry_path": "packs",
        "public_root_path": "public",
        "public_output_path": "packs",
        "cache_path": "tmp/cache/webpacker",
        "webpack_compile_output": true,
        "additional_paths": [],
        "cache_manifest": false,
        "extract_css": false,
        "static_assets_extensions": [
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".tiff",
            ".ico",
            ".svg",
            ".eot",
            ".otf",
            ".ttf",
            ".woff",
            ".woff2"
        ],
        "extensions": [
            ".mjs",
            ".js",
            ".sass",
            ".scss",
            ".css",
            ".module.sass",
            ".module.scss",
            ".module.css",
            ".png",
            ".svg",
            ".gif",
            ".jpeg",
            ".jpg"
        ],
        "compile": true,
        "dev_server": {
            "https": false,
            "host": "localhost",
            "port": 3035,
            "public": "localhost:3035",
            "hmr": false,
            "inline": true,
            "overlay": true,
            "compress": true,
            "disable_host_check": true,
            "use_local_ip": false,
            "quiet": false,
            "pretty": false,
            "headers": {
                "Access-Control-Allow-Origin": "*"
            },
            "watch_options": {
                "ignored": "**/node_modules/**"
            }
        }
    },
    "test": {
        "source_path": "app/javascript",
        "source_entry_path": "packs",
        "public_root_path": "public",
        "public_output_path": "packs-test",
        "cache_path": "tmp/cache/webpacker",
        "webpack_compile_output": true,
        "additional_paths": [],
        "cache_manifest": false,
        "extract_css": false,
        "static_assets_extensions": [
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".tiff",
            ".ico",
            ".svg",
            ".eot",
            ".otf",
            ".ttf",
            ".woff",
            ".woff2"
        ],
        "extensions": [
            ".mjs",
            ".js",
            ".sass",
            ".scss",
            ".css",
            ".module.sass",
            ".module.scss",
            ".module.css",
            ".png",
            ".svg",
            ".gif",
            ".jpeg",
            ".jpg"
        ],
        "compile": true
    },
    "production": {
        "source_path": "app/javascript",
        "source_entry_path": "packs",
        "public_root_path": "public",
        "public_output_path": "packs",
        "cache_path": "tmp/cache/webpacker",
        "webpack_compile_output": true,
        "additional_paths": [],
        "cache_manifest": true,
        "extract_css": true,
        "static_assets_extensions": [
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".tiff",
            ".ico",
            ".svg",
            ".eot",
            ".otf",
            ".ttf",
            ".woff",
            ".woff2"
        ],
        "extensions": [
            ".mjs",
            ".js",
            ".sass",
            ".scss",
            ".css",
            ".module.sass",
            ".module.scss",
            ".module.css",
            ".png",
            ".svg",
            ".gif",
            ".jpeg",
            ".jpg"
        ],
        "compile": false
    }
}



以上。