0

Case: Development environment log level is DEBUG while Production is INFO. I want to use every default log configuration and overwrite only level if environment == develoment.

Problem: first level configs can be over-written but not sub levels.

Consider Example Code:

#file: config.rb

default = Configuration.for('default'){
  log {
    file '/tmp/foo.log'
    level 'WARN'
    freq 'daily'
  }
}

development = Configuration.for( 'development', default) {
  log {
    level 'DEBUG'
  }
}

In main file, I use the above code like so

# main.rb

require 'config.rb'    
$CONFIG = Configuration.for $DEV_ENV # either ('default' || 'development')
p $CONFIG.log.freq

I get an method missing error:

`undefined method `freq' for #<Configuration:0x00000003a65d80> (NoMethodError)`

The only (ugly) solution i have is to point file and freq values back to default like so:

  log {
    file default.log.file
    level 'DEBUG'
    freq default.log.freq
  }

EEWWW!! Nasty!

Any other suggestions? I've tried to implement something like this with SettingsLogic and Configatron too at no avail. There goes the three top configuration gems for Ruby. Do I need to make my own?? Is this really such an exotic example?

Would love your feedback or suggestions.

dlite922
  • 1,924
  • 3
  • 24
  • 60
  • I guess I could so something like log_level, log_file, log_freq and all be under the first node. Still not pretty. – dlite922 Jan 07 '13 at 23:51
  • If I imagine that Configuration calls the block, I get `undefined method 'log' for main:Object` and I'm not surprised by your error. If `$CONFIG.log` returns an instance of Configuration, it means that `log` has been defined explicitly or by method_missing as an instance method of Configuration. All the magic probably happens in Configuration and you should show it so that we can see what's going on. – BernardK Jan 08 '13 at 09:10
  • Configuration is not my class. it's the the #1 ruby configuration tool by number of downloads. :) – dlite922 Jan 08 '13 at 21:56
  • Seems unable to access inner default data. And the second log overwrites the first (run ruby with -w option). Also see http://stackoverflow.com/questions/8594433/ruby-configuration-gem-nested-properties-not-working. No good answer. – BernardK Jan 09 '13 at 18:02
  • reason why I just don't use a hash (I should at this point) is I started out with a YAML-type config file (Settingslogic). So that you don't need programmers to configure the app. Config files are consistent if they're all the same format for all company-wide applications. – dlite922 Jan 09 '13 at 23:17
  • Do you abandon Configuration ? I was studying it to see how it works, but it's difficult because there is not a single comment. I wonder why it is #1. – BernardK Jan 09 '13 at 23:25
  • It's a popularity contest I guess. The name also helps: it's generic and plain. At this point, a 2,3 level hash is more clear than this "Configuration.for" non-sense. – dlite922 Jan 10 '13 at 16:37

1 Answers1

0

I was able to solve your problem with SettingsLogic and anchor labels in YAML.

My config file:

defaults: &defaults
  log: &logdefault
      file:  /tmp/foo.log
      level: WARN
      freq: daily

development:
  <<: *defaults
  log:
      <<: *logdefault
      level: DEBUG

test:
  <<: *defaults

production:
  <<: *defaults

The trick is to store the defaults in an anchor label and re-use it, when you try to redefine a part of it. You need an anchor for each level.

You can use it as

require 'settingslogic'  #https://github.com/settingslogic/settingslogic
class SettingsDEV < Settingslogic
  source "./application.yml"
  namespace 'development'
end
p SettingsDEV.log #{"file"=>"/tmp/foo.log", "level"=>"DEBUG", "freq"=>"daily"}

class SettingsProd < Settingslogic
  source "./application.yml"
  namespace 'production'
end
p SettingsProd.log  #{"file"=>"/tmp/foo.log", "level"=>"WARN", "freq"=>"daily"}
knut
  • 27,320
  • 6
  • 84
  • 112