当たり前なんですけど、部分的に切り取ると違和感があるので言葉でまとめる
環境
config (4.2.1)
gemそのもののリポジトリは以下 rubyconfig/config: Easiest way to add multi-environment yaml settings to Rails, Sinatra, Pandrino and other Ruby projects.
上書き挙動について
configのgemは公式のREADMEにも記載がある通り、config/settings.yml
を起点に環境名のymlでoverrideしていく。
具体例
たとえば以下のようにconfig/settings.yml
を書いたとする
default_user_data: id: example_default_user email: default_example@example.com max_eat_fruits_count: orange: 5 melon: 1 banana: 4 favorite_sports: - baseball - soccer
そして、config/settings/development.yml
を以下のように記述する。
default_user_data: id: example_user email: example@example.com max_eat_fruits_count: orange: 10 apple: 2 banana: 5 favorite_sports: - basketball - soccer
この場合、config/settings/development.yml
の設定が上書きされるので、RAILS_ENVがdevelopmentの場合、元々のconfig/settings.yml
にも存在するキーの値は上書きされる。
pp Settings.default_user_data.id "example_user"
またArrayもあとがちとなる。
pp Settings.default_user_data.favorite_sports ["basketball", "soccer"]
このように default_user_data
起点で考えると、id
も email
も favorite_sports
も上書きになっているので、 max_eat_fruits_count
も上書きされるように見えるがそうはならない
pp Settings.default_user_data.max_eat_fruits_count.each { |key, value| pp "#{key} => #{value}" } "orange => 10" "melon => 1" "banana => 5" "apple => 2"
(よくよく考えれば当たり前だが)これはyml全体がhashなので、上書きされるとした場合に機能として成立しなくなるのでこのような挙動となる。
mergeされたくないHashがある場合はarrayで代替するしかない
原則Hash的な記法で記述をするとmergeされてしまうし、それを防ぐと全滝的に上書きする仕組みが機能しない。そのためもし「Hash的に扱いたいが、特定階層以下はmergeしないでほしい」という場合は苦肉の策としてarrayとHashを組み合わせるなどの方法を取るしかない。
たとえば以下のようにconfig/settings.yml
を書いたとする
default_user_data: max_eat_fruits_count: - orange: 5 - melon: 1 - banana: 4
default_user_data: max_eat_fruits_count: - orange: 10 - apple: 2 - banana: 5
このようにしてやればArrayなので上書きされる
pp Settings.default_user_data.max_eat_fruits_count.each { |hash_obj| hash_obj.each{|key,value| pp "#{key} => #{value}" }} "orange => 10" "apple => 2" "banana => 5"
そして以下のように取得すればHashとして扱うことも可能となる
result = {}.merge(*Settings.default_user_data.max_eat_fruits_count) pp result {:orange=>10, :apple=>2, :banana=>5}
ただかなり無理やりなので、マージを避けなければいけない値がある場合は管理手法を見直したほうが良い