Class: Picnic::Conf

Inherits:
Object
  • Object
show all
Defined in:
lib/picnic/conf.rb

Overview

Provides an interface for accessing your Picnic app’s configuration file.

Usage example:

# Load the configuration from /etc/foo/config.yml
Conf.load('foo')

# The contents of config.yml is now available as follows:
puts Conf[:server]
puts Conf[:authentication][:username]
# ... etc.

Defined Under Namespace

Classes: Error

Instance Method Summary collapse

Constructor Details

#initialize(from_hash = {}) ⇒ Conf

Returns a new instance of Conf.



16
17
18
19
20
21
22
23
# File 'lib/picnic/conf.rb', line 16

def initialize(from_hash = {})
  @conf = HashWithIndifferentAccess.new(from_hash)
  
  @conf[:log] ||= HashWithIndifferentAccess.new
  @conf[:log].merge!(:file => STDOUT, :level => 'DEBUG')
  
  @conf[:uri_path] ||= "/"
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

Another way of reading or writing a configuration option.

The following statements are equivalent:

puts conf[:server]
puts conf.server

These are also equivalent:

conf[:server] = 'mongrel'
conf.server = 'mongrel'


50
51
52
53
54
55
56
# File 'lib/picnic/conf.rb', line 50

def method_missing(method, *args)
  if method.to_s =~ /(.*?)=$/
    self[$~[1]] = args.first
  else
    self[method]
  end
end

Instance Method Details

#[](key) ⇒ Object

Read a configuration option.

For example:

puts conf[:server]


29
30
31
# File 'lib/picnic/conf.rb', line 29

def [](key)
  @conf[key]
end

#[]=(key, value) ⇒ Object

Set a configuration option.

For example:

conf[:server] = 'mongrel'


37
38
39
# File 'lib/picnic/conf.rb', line 37

def []=(key, value)
  @conf[key] = value
end

#copy_example_config_file(app_name, app_root, dest_conf_file) ⇒ Object

Copies the example config file into the appropriate configuration directory.

app_name

The name of your application. For example: foo

app_root

The path to your application’s root directory. For example: /srv/www/camping/foo/

+dest_conf_file

The path where the example conf file should be copied to. For example: /etc/foo/config.yml



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/picnic/conf.rb', line 81

def copy_example_config_file(app_name, app_root, dest_conf_file)
  require 'fileutils'
      
  example_conf_file = example_config_file_path(app_root)
  
  puts "\n#{app_name.to_s.upcase} SERVER HAS NOT YET BEEN CONFIGURED!!!\n"
  puts "\nAttempting to copy sample configuration from '#{example_conf_file}' to '#{dest_conf_file}'...\n"
  
  unless File.exists? example_conf_file 
    puts "\nThe example conf file does not exist! The author of #{app_name} may have forgotten to include it. You'll have to create the config file manually.\n"
    exit 2
  end
  
  begin
    dest_conf_file_dir = File.dirname(dest_conf_file)
    FileUtils.mkpath(dest_conf_file_dir) unless File.exists? dest_conf_file_dir
    FileUtils.cp(example_conf_file, dest_conf_file)
  rescue Errno::EACCES
    puts "\nIt appears that you do not have permissions to create the '#{dest_conf_file}' file. Try running this command using sudo (as root).\n"
    exit 2
  rescue => e
    puts "\nFor some reason the '#{dest_conf_file}' file could not be created (#{e})."
    puts "You'll have to copy the file manually. Use '#{example_conf_file}' as a template.\n"  
    exit 2
  end
  
  puts "\nA sample configuration has been created for you in '#{dest_conf_file}'. Please edit this file to" +
    " suit your needs and then run #{app_name} again.\n"
  exit 1
end

#determine_config_filename(app_name, app_root, config_file = nil) ⇒ Object

Business logic for deriving the current config file name.



113
114
115
# File 'lib/picnic/conf.rb', line 113

def determine_config_filename(app_name, app_root, config_file = nil)
  config_file || "/etc/#{app_name.to_s.downcase}/config.yml"
end

#example_config_file_path(app_root) ⇒ Object

Returns the path to your application’s example config file.

The example config file should be in the root directory of your application’s distribution package and should be called config.example.yml. This file is used as a template for your app’s configuration, to be customized by the end user.



70
71
72
# File 'lib/picnic/conf.rb', line 70

def example_config_file_path(app_root)
  "#{app_root}/config.example.yml"
end

#load_from_file(app_name, app_root, config_file = nil) ⇒ Object

Loads the configuration from the YAML file for the given app.

app_name should be the name of your app; for example: foo

app_root should be the path to your application’s root directory; for example

/srv/www/camping/foo/

config_file

can be the path to an alternate location for the config file to load

By default, the configuration will be loaded from /etc/<app_name>/config.yml.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/picnic/conf.rb', line 124

def load_from_file(app_name, app_root, config_file = nil)
  conf_file = determine_config_filename(app_name, app_root, config_file)
  
  puts "Loading configuration for #{app_name.inspect} from #{conf_file.inspect}..."
  
  begin
    conf_file = etc_conf = conf_file
    unless File.exists? conf_file 
      # can use local config.yml file in case we're running non-gem installation
      conf_file = "#{app_root}/config.yml"
    end
  
    unless File.exists? conf_file  
      copy_example_config_file(app_name, app_root, etc_conf)
    end
    
    loaded_conf = HashWithIndifferentAccess.new(YAML.load_file(conf_file))
    
    @conf.merge!(loaded_conf)
    
  rescue => e
      raise "Your #{app_name} configuration may be invalid."+
        " Please double-check check your config.yml file."+
        " Make sure that you are using spaces instead of tabs for your indentation!!" +
        "\n\nTHE UNDERLYING ERROR WAS:\n#{e.inspect}"
  end
end

#merge_defaults(defaults) ⇒ Object



152
153
154
# File 'lib/picnic/conf.rb', line 152

def merge_defaults(defaults)
  @conf = HashWithIndifferentAccess.new(HashWithIndifferentAccess.new(defaults).merge(@conf))
end

#respond_to?(method) ⇒ Boolean

Needs to be defined when we have a custom method_missing().

Returns:

  • (Boolean)


59
60
61
# File 'lib/picnic/conf.rb', line 59

def respond_to?(method)
  (@conf.stringify_keys.keys).include?(method.to_s) || super
end