Skip to content

Optional namespace for add_source! #288

@wwboynton

Description

@wwboynton

It would be nice to be able to invoke Settings.add_source! with an optional parent prefix such that new sources could be loaded in programmatically into different levels of the Settings structure. This would allow for multiple YAML files of similar function to be grouped under the same parent without having to specify that namespace in every single YAML file.

In my case, I have a lot of user-defined YAML files together in a directory which are split up for organization/legibility, but which cohabitate in the same parent node of the Settings object when all loaded together. It's confusing to ask my users to specify a few levels of parent nodes at the top of every single file in the directory just so that the Settings object will be correctly organized when it gets to my code. It would be nice to write code which will load these YAML files into the Settings object in a way that mimics their directory structure on the filesystem.

Modifying the yaml_source.rb source to accommodate this might look something like this:

# config/lib/config/sources/yaml_source.rb 

module Config
  module Sources
    class YAMLSource
      attr_accessor :path

      def initialize(path, namespace = nil)  # New variable here
        @path = path.to_s
        @namespace = namespace 
      end

      # returns a config hash from the YML file
      def load
        result = YAML.load(ERB.new(IO.read(@path)).result) if @path and File.exist?(@path)

        if [email protected]? && result        # New logic here
          result = @namespace.reverse.inject(result) { |a, n| { n => a } }
        end
        result || {}
        rescue Psych::SyntaxError => e
      
        # ...etc

Running that like so:

puts "Without Namespace!"
y = Config::Sources::YAMLSource.new("/Users/userguy/repos/scratch/example.yml")
pp y.load

puts "With Namespace!"
y = Config::Sources::YAMLSource.new("/Users/userguy/repos/scratch/example.yml", ['new-level'])
pp y.load

...produces output like this:

Without Namespace!
{"foo"=>["bar", "baz", {"chungus"=>["Bungus"]}]}
With Namespace!
{"new-level"=>{"foo"=>["bar", "baz", {"chungus"=>["Bungus"]}]}}

If you'd like me to take a crack at doing this and submitting a PR, let me know and I'm happy to do it. Maybe I am just very tired and completely missed an existing way to do this in the documentation, or am overthinking this and forgetting something fundamental about YAML that will solve my problem. It has been known to happen, in which case please close this issue and accept my apologies for wasting your time!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions