Permalink
Browse files

Complete rewrite, see changelog / readme

  • Loading branch information...
1 parent 14e9336 commit 471adcb09c8ff303a2f024489480ba3573b20024 @binarylogic committed Aug 22, 2009
View
@@ -1,3 +1,7 @@
+== 2.0.0 released 2009-08-22
+
+* Less magic, instead of automatically defining a Settings constant, you should define your own constant. See the readme for an example.
+
== 1.0.3 released 2009-04-23
* Fix Settings initialized with a Hash to work with both symbol and string hash keys.
View
@@ -1,6 +1,6 @@
= Settingslogic
-Settingslogic is an old library of mine that I decided to go ahead and share with the world. It's nothing crazy or new. Just a simple solution to a simple problem. Settingslogic provides globally accessible settings via an ERB enabled YAML file using a singleton design pattern. It has been great for my apps, maybe you will enjoy it too.
+Settingslogic is a simple configuration / settings solution that uses an ERB enabled YAML file. It has been great for my apps, maybe you will enjoy it too.
So here is my question to you.....is Settingslogic a great settings solution or the greatest?
@@ -24,9 +24,22 @@ Or as a plugin
script/plugin install git://github.com/binarylogic/settingslogic.git
-== Create your settings
+== 1. Define your constant
-By default Settingslogic tries to load config/application.yml. This is just a typical YAML file, notice ERB is allowed.
+Instead of defining a Settings constant for you, that task is left to you. Simply create a class in your application that looks like:
+
+ class Settings < Settingslogic
+ source "#{Rails.root}/config/application.yml"
+ namespace Rails.env
+ end
+
+Name it Settings, name it Config, name it whatever you want. Add as many or as few as you like. A good place to put this file in a rails app is models/settings.rb
+
+I felt adding a settings file in your app was more straightforward, less tricky, and more flexible.
+
+== 2. Create your settings
+
+Notice above we specified an absolute path to our settings file called "application.yml". This is just a typical YAML file. Also notice above that we specified a namespace for our environment. This allows us to namespace our configuration depending on our environment:
# app/config/application.yml
defaults: &defaults
@@ -45,12 +58,10 @@ By default Settingslogic tries to load config/application.yml. This is just a ty
production:
<<: *defaults
-Take note of the environment namespacing. If your framework supports environments this is a good way to support environment specific settings. If you are using this in an area where there are no environment disregard the namespacing. It will work just fine without it.
-
== Access your settings
- >> RAILS_ENV
- => "development"
+ >> Rails.env.development?
+ => true
>> Settings.cool
=> "#<Settingslogic::Settings ... >"
@@ -64,24 +75,5 @@ Take note of the environment namespacing. If your framework supports environment
>> Settings.awesome_setting
=> "Did you know 5 + 5 = 10?"
-== Multiple settings
-
- settings1 = Settings.new(:settings1) # looks for config/settings1.yml
- settings2 = Settings.new("settings2.yaml") # looks for settings2.yml
- settings2 = Settings.new("/abs/path/settings2.yaml") # looks for /abs/path/settings2.yml
- settings3 = Settings.new(:some_setting => "some value")
-
-== Configure
-
-Configuration is optional. See Settingslogic::Config for more details.
-
- # config/initializers/settingslogic.rb
- Settingslogic::Config.configure do |config|
- config.file_name = :config # will look for config/config.yml
- config.file_name = "config" # will look for config
- config.file_name = "config.yaml" # will look for confg.yaml
- config.file_name = "/absolute/path/config.yml" # will look for /absolute/path/config.yml
- end
-
Copyright (c) 2008 {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com], released under the MIT license
View
@@ -10,40 +10,24 @@ begin
gem.homepage = "http://github.com/binarylogic/settingslogic"
gem.authors = ["Ben Johnson of Binary Logic"]
gem.rubyforge_project = "settingslogic"
- gem.add_dependency "activesupport"
end
+ Jeweler::RubyforgeTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
end
-require 'rake/testtask'
-Rake::TestTask.new(:test) do |test|
- test.libs << 'lib' << 'test'
- test.pattern = 'test/**/*_test.rb'
- test.verbose = true
+require 'spec/rake/spectask'
+Spec::Rake::SpecTask.new(:spec) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.spec_files = FileList['spec/**/*_spec.rb']
end
-begin
- require 'rcov/rcovtask'
- Rcov::RcovTask.new do |test|
- test.libs << 'test'
- test.pattern = 'test/**/*_test.rb'
- test.verbose = true
- end
-rescue LoadError
- task :rcov do
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
- end
+Spec::Rake::SpecTask.new(:rcov) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.pattern = 'spec/**/*_spec.rb'
+ spec.rcov = true
end
-task :default => :test
+task :spec => :check_dependencies
-begin
- require 'rake/contrib/sshpublisher'
- namespace :rubyforge do
- desc "Release gem to RubyForge"
- task :release => ["rubyforge:release:gem"]
- end
-rescue LoadError
- puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
-end
+task :default => :spec
View
@@ -1,13 +1,86 @@
require "yaml"
require "erb"
-require File.dirname(__FILE__) + "/settingslogic/config"
-require File.dirname(__FILE__) + "/settingslogic/settings"
-# Try to load conflicting Settings classes
-begin
- Settings
-rescue(NameError)
-end
-
-# Since we don't have a Settings constant, lets go ahead and use it
-::Settings = Settingslogic::Settings unless defined?(Settings)
+# A simple settings solution using a YAML file. See README for more information.
+class Settingslogic < Hash
+ class UndefinedSetting < StandardError; end
+
+ class << self
+ def name # :nodoc:
+ instance.key?("name") ? instance.name : super
+ end
+
+ def source(value = nil)
+ if value.nil?
+ @source
+ else
+ @source = value
+ end
+ end
+
+ def namespace(value = nil)
+ if value.nil?
+ @namespace
+ else
+ @namespace = value
+ end
+ end
+
+ private
+ def instance
+ @instance ||= new
+ end
+
+ def method_missing(name, *args, &block)
+ instance.send(name, *args, &block)
+ end
+ end
+
+ # Initializes a new settings object. You can initialize an object in any of the following ways:
+ #
+ # Settings.new(:application) # will look for config/application.yml
+ # Settings.new("application.yaml") # will look for application.yaml
+ # Settings.new("/var/configs/application.yml") # will look for /var/configs/application.yml
+ # Settings.new(:config1 => 1, :config2 => 2)
+ #
+ # Basically if you pass a symbol it will look for that file in the configs directory of your rails app, if you are using this in rails. If you pass a string it should be an absolute path to your settings file.
+ # Then you can pass a hash, and it just allows you to access the hash via methods.
+ def initialize(hash_or_file = self.class.source)
+ case hash_or_file
+ when Hash
+ self.update hash_or_file
+ else
+ self.update YAML.load(ERB.new(File.read(hash_or_file)).result).to_hash
+ self.update self[self.class.namespace] if self.class.namespace
+ end
+
+ define_settings!
+ end
+
+ private
+ def method_missing(name, *args, &block)
+ raise UndefinedSetting.new("The '#{name}' was not found in your configuration file: #{self.class.source}")
+ end
+
+ def define_settings!
+ self.each do |key, value|
+ case value
+ when Hash
+ instance_eval <<-"end_eval", __FILE__, __LINE__
+ def #{key}
+ @#{key} ||= self.class.new(self[#{key.inspect}])
+ end
+ end_eval
+ else
+ instance_eval <<-"end_eval", __FILE__, __LINE__
+ def #{key}
+ @#{key} ||= self[#{key.inspect}]
+ end
+ def #{key}=(value)
+ @#{key} = value
+ end
+ end_eval
+ end
+ end
+ end
+end
@@ -1,25 +0,0 @@
-module Settingslogic
- # Sets configuration on Settingslogic.
- class Config
- class << self
- def configure
- yield self
- end
-
- # The name of the file that your settings will be stored for singleton access. Meaning the settings file that will be used when calling methods on the class level:
- #
- # Settings.setting1
- # Settings.setting2
- # # etc...
- #
- # All that you need to do is specify the name of the file. It will automatically look in the config directory.
- #
- # * <tt>Default:</tt> :application
- # * <tt>Accepts:</tt> Symbol or String
- def settings_file
- @settings_file ||= :application
- end
- attr_writer :settings_file
- end
- end
-end
@@ -1,80 +0,0 @@
-module Settingslogic
- # A simple settings solution using a YAML file. See README for more information.
- class Settings < Hash
- class << self
- def name # :nodoc:
- instance.key?("name") ? instance.name : super
- end
-
- # Resets the singleton instance. Useful if you are changing the configuration on the fly. If you are changing the configuration on the fly you should consider creating instances.
- def reset!
- @instance = nil
- end
-
- private
- def instance
- @instance ||= new
- end
-
- def method_missing(name, *args, &block)
- instance.send(name, *args, &block)
- end
- end
-
- attr_accessor :_settings
-
- # Initializes a new settings object. You can initialize an object in any of the following ways:
- #
- # Settings.new(:application) # will look for config/application.yml
- # Settings.new("application.yaml") # will look for application.yaml
- # Settings.new("/var/configs/application.yml") # will look for /var/configs/application.yml
- # Settings.new(:config1 => 1, :config2 => 2)
- #
- # Basically if you pass a symbol it will look for that file in the configs directory of your rails app, if you are using this in rails. If you pass a string it should be an absolute path to your settings file.
- # Then you can pass a hash, and it just allows you to access the hash via methods.
- def initialize(name_or_hash = Config.settings_file)
- case name_or_hash
- when Hash
- self.update name_or_hash
- when String, Symbol
- root_path = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/config/" : ""
- file_path = name_or_hash.is_a?(Symbol) ? "#{root_path}#{name_or_hash}.yml" : name_or_hash
- self.update YAML.load(ERB.new(File.read(file_path)).result).to_hash
- else
- raise ArgumentError.new("Your settings must be a hash, a symbol representing the name of the .yml file in your config directory, or a string representing the abosolute path to your settings file.")
- end
- if defined?(RAILS_ENV)
- rails_env = self.keys.include?(RAILS_ENV) ? RAILS_ENV : RAILS_ENV.to_sym
- self.update self[rails_env] if self[rails_env]
- end
- define_settings!
- end
-
- private
- def method_missing(name, *args, &block)
- raise NoMethodError.new("no configuration was specified for #{name}")
- end
-
- def define_settings!
- self.each do |key, value|
- case value
- when Hash
- instance_eval <<-"end_eval", __FILE__, __LINE__
- def #{key}
- @#{key} ||= self.class.new(self[#{key.inspect}])
- end
- end_eval
- else
- instance_eval <<-"end_eval", __FILE__, __LINE__
- def #{key}
- @#{key} ||= self[#{key.inspect}]
- end
- def #{key}=(value)
- @#{key} = value
- end
- end_eval
- end
- end
- end
- end
-end
View
@@ -0,0 +1,3 @@
+class Settings < Settingslogic
+ source "#{File.dirname(__FILE__)}/settings.yml"
+end
File renamed without changes.
View
@@ -0,0 +1,4 @@
+class Settings2 < Settingslogic
+ source "#{File.dirname(__FILE__)}/settings.yml"
+ namespace "setting1"
+end
View
@@ -0,0 +1,27 @@
+require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
+
+describe "Settingslogic" do
+ it "should be a hash" do
+ Settings.send(:instance).should be_is_a(Hash)
+ end
+
+ it "should access settings" do
+ Settings.setting1.should == {"setting1_child" => "saweet"}
+ end
+
+ it "should access nested settings" do
+ Settings.setting1.setting1_child.should == "saweet"
+ end
+
+ it "should enable erb" do
+ Settings.setting3.should == 25
+ end
+
+ it "should raise an error for unfound settings" do
+ lambda { Settings.undefined }.should raise_error(Settingslogic::UndefinedSetting)
+ end
+
+ it "should namespace settings" do
+ Settings2.setting1_child.should == "saweet"
+ end
+end
View
@@ -0,0 +1,12 @@
+require 'spec'
+require 'rubygems'
+require 'ruby-debug'
+
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+require 'settingslogic'
+require 'settings'
+require 'settings2'
+
+Spec::Runner.configure do |config|
+end
Oops, something went wrong.

0 comments on commit 471adcb

Please sign in to comment.