lib/figleaf/settings.rb in figleaf-0.0.7 vs lib/figleaf/settings.rb in figleaf-0.2.0

- old
+ new

@@ -1,6 +1,119 @@ module Figleaf class Settings - include Figleaf::Configuration - include Figleaf::LoadSettings + class << self + class_attribute :auto_define + self.auto_define = false + + # Public - configure pre-defined attributes + # + def configure + self.auto_define.tap do |cached_auto_define| + self.auto_define = false + yield self + self.auto_define = cached_auto_define + end + end + + # Public - configure auto defined settings attributes + # and load yaml settings from confing/settings directory + # + def configure!(&block) + load_settings + configure_with_auto_define(&block) + end + + def configure_with_auto_define + self.auto_define.tap do |cached_auto_define| + self.auto_define = true + yield self + self.auto_define = cached_auto_define + end + end + + # Load all files in config/settings and set their contents as first level + # citizen of Settings: + # config/settings/some_service.yml contains + # production: + # foo: bar + # --> Settings.some_service.foo = bar + def load_settings(file_pattern = default_file_pattern, env_to_load = env) + configure_with_auto_define do + Dir.glob(file_pattern).each do |file| + property_name = File.basename(file, '.yml') + yaml_hash = load_file(file) or next + property = yaml_hash[env_to_load] + + next if property.nil? + + if self.respond_to?(property_name) && + self.send(property_name).respond_to?(:merge) && + property.respond_to?(:merge) + property = self.send(property_name).merge(property) + end + + self.send("#{property_name}=", property) + end + end + end + + def load_file(file_path, env = nil) + property = YAML.load(ERB.new(IO.read(file_path)).result) + property = property[env] if env + use_hashie_if_hash(property) + end + + def root + return Rails.root if defined?(Rails) + Pathname.new('.') + end + + def default_file_pattern + root.join('config/settings/*.yml') + end + + def env + return Rails.env if defined?(Rails) + ENV['ENVIRONMENT'] + end + + def use_hashie_if_hash(property) + return Figleaf::Fighash.new(property) if property.is_a?(Hash) + property + end + + def override_with_local!(local_file) + #this file (i.e. test.local.rb) is an optional place to put settings + local_file.tap do |local_settings_path| + eval(IO.read(local_settings_path), binding) if File.exists?(local_settings_path) + end + end + + def method_missing(method_name, *args) + getter_name, modifier = extract_getter_name_and_modifier(method_name) + + if self.auto_define && modifier == '=' && args.length == 1 + self.define_cattr_methods(getter_name) + self.send(method_name, args.shift) + elsif modifier == '?' && args.empty? + self.send(getter_name).present? + else + super + end + end + + def extract_getter_name_and_modifier(method_name) + match = method_name.to_s.match(/(?<name>.*?)(?<modifier>[?=]?)$/) + [match[:name], match[:modifier]] + end + + def define_cattr_methods(getter_name) + cattr_writer getter_name + define_singleton_method(getter_name) do + result = class_variable_get "@@#{getter_name}" + result.respond_to?(:call) ? result.call : result + end + end + + end end end