Permalink
Browse files

First version.

  • Loading branch information...
stephencelis committed Apr 2, 2009
0 parents commit cdc8bf7e8db4f563d7cee2fa5df4930dd0b989ed
Showing with 279 additions and 0 deletions.
  1. +5 −0 History.txt
  2. +11 −0 Manifest.txt
  3. +96 −0 README.rdoc
  4. +23 −0 Rakefile
  5. +7 −0 generators/app_config/app_config_generator.rb
  6. +20 −0 generators/app_config/templates/app.yml
  7. +3 −0 init.rb
  8. +1 −0 install.rb
  9. +51 −0 lib/app.rb
  10. +55 −0 test/app_test.rb
  11. +7 −0 uninstall.rb
@@ -0,0 +1,5 @@
+=== 0.1.0 / 2009-04-02
+
+* 1 major enhancement
+
+ * Birthday!
@@ -0,0 +1,11 @@
+History.txt
+Manifest.txt
+README.rdoc
+Rakefile
+generators/app_config/app_config_generator.rb
+generators/app_config/templates/app.yml
+init.rb
+install.rb
+lib/app.rb
+test/app_test.rb
+uninstall.rb
@@ -0,0 +1,96 @@
+= App
+
+http://github.com/stephencelis/app
+
+
+== DESCRIPTION
+
+Move the config out of your app, and into App.
+
+Sure, it's been done before, and others will do it again, but this is my way,
+and I like it.
+
+
+== FEATURES/PROBLEMS
+
+* Easy, environmentally-friendly configuration access.
+
+
+For mutability, try acts_as_singleton or KVC:
+
+* http://github.com/stephencelis/acts_as_singleton
+* http://github.com/stephencelis/kvc
+
+
+== SYNOPSIS
+
+App looks for and loads configuration from "config/app.yml", providing a
+namespaced API for access.
+
+ App.config # => {"apis"=>{"flickr"=>{ ... }}
+
+
+Sugar is always sweeter:
+
+ App.config("apis", "flickr") # => App.config["apis"]["flickr"]
+
+
+Who doesn't like sugar?
+
+ App["apis", "flickr"]
+
+
+Sugar, sugar, sugar.
+
+ App.apis("flickr")
+
+
+Let's not overcomplicate things, though. <tt>App.apis.flickr</tt> just doesn't
+look right.
+
+
+== REQUIREMENTS
+
+* Rails 2.3.2 or greater.
+
+
+== INSTALL
+
+Install:
+
+ % script/plugin install git://github.com/stephencelis/app.git
+
+
+Or submodule:
+
+ % git submodule add git://github.com/stephencelis/app.git vendor/plugins/app
+
+
+And generate:
+
+ % script/generate app_config
+
+
+== LICENSE
+
+(The MIT License)
+
+(c) 2009-* Stephen Celis, stephen@stephencelis.com.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the app plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the app plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'App'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1,7 @@
+class AppConfigGenerator < Rails::Generator::Base
+ def manifest
+ record do |m|
+ m.file "app.yml", "config/app.yml"
+ end
+ end
+end
@@ -0,0 +1,20 @@
+# Your app config, provided by the App plugin.
+#
+# See "vendor/plugins/app/README.txt" for details.
+---
+development: &development
+ loaded_at: <%= Time.zone.now.iso8601 %>
+ apis:
+ braintree:
+ :login: testapi
+ :password: password1
+
+test:
+ <<: *development
+
+production:
+ loaded_at: <%= Time.zone.now.iso8601 %>
+ apis:
+ braintree:
+ :login: testapi
+ :password: password1
@@ -0,0 +1,3 @@
+if !File.exist? Rails.root.join("config", "app.yml")
+ puts '** App: "config/app.yml" not found. Run `script/generate app_config`.'
+end
@@ -0,0 +1 @@
+STDOUT.puts 'Run `script/generate app_config` to generate "config/app.yml".'
@@ -0,0 +1,51 @@
+# App is your app.
+#
+# What would your app be without it? Still an app, but without the App.
+module App
+ VERSION = "0.1.0"
+
+ raw_config = File.read Rails.root.join("config", "app.yml")
+ @@config = YAML.load(ERB.new(raw_config).result)[Rails.env].freeze
+
+ class << self
+ # Returns the application configuration hash, as defined in
+ # "config/app.yml".
+ #
+ # Follows args through the hash tree. E.g.:
+ #
+ # App.config("apis", "flickr") # => config_hash["apis"]["flickr"]
+ #
+ # <tt>App.config</tt> is aliased to <tt>App.[]</tt>, so shorten things up:
+ #
+ # App["apis", "flickr"]
+ #
+ # Or rely on +method_missing+ to make it even shorter (and sweeter):
+ #
+ # App.apis("flickr")
+ def config(*args)
+ @@config if args.empty?
+ args.inject(@@config) { |config, arg| config[arg] }
+ end
+
+ alias [] config
+ alias __name__ name
+
+ # Returns the name of the web application, which can be overridden in
+ # "config/app.yml".
+ #
+ # To return the name of the module, use <tt>App.__name__</tt>.
+ def name
+ @@name ||= method_missing(:name) || File.basename(Rails.root)
+ end
+
+ def inspect
+ "#<App: #{config.inspect}>"
+ end
+
+ private
+
+ def method_missing(method, *args)
+ self[method.to_s, *args] || self[method, *args]
+ end
+ end
+end
@@ -0,0 +1,55 @@
+require 'test/unit'
+require 'rubygems'
+require 'active_support'
+require 'active_support/test_case'
+require 'mocha'
+require 'erb'
+
+# Mock
+module App
+ module Rails
+ def self.root
+ File
+ end
+ def self.env
+ "development"
+ end
+ end
+end
+
+File.stubs(:read).returns <<-YAML
+---
+development:
+ loaded_at: <%= Time.now.iso8601 %>
+ username: Stephen
+ password: frobozz
+ apis:
+ braintree:
+ :login: testapi
+ :password: password1
+YAML
+
+require 'app'
+
+class AppTest < ActiveSupport::TestCase
+ test "different ways of access should return same values" do
+ assert_equal "Stephen", App.config["username"]
+ assert_equal "Stephen", App.config("username")
+ assert_equal "Stephen", App["username"]
+ assert_equal "Stephen", App.username
+
+ assert_equal "testapi", App.config["apis"]["braintree"][:login]
+ assert_equal "testapi", App.config("apis", "braintree", :login)
+ assert_equal "testapi", App["apis", "braintree", :login]
+ assert_equal "testapi", App.apis("braintree", :login)
+ end
+
+ test "ERB should be parsed" do
+ assert_instance_of Time, App.loaded_at
+ end
+
+ test "App.name should be inferred" do
+ File.stubs(:basename).returns "root"
+ assert_equal "root", App.name
+ end
+end
@@ -0,0 +1,7 @@
+app_yaml = Rails.root.join("config", "app.yml")
+if File.exist? app_yaml
+ print 'Also remove "config/app.yml"? [yN] '
+ if STDIN.gets.chomp =~ /^y)/i
+ File.delete app_yaml
+ end
+end

0 comments on commit cdc8bf7

Please sign in to comment.