rubycut-sinatra-contrib 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +136 -0
  3. data/Rakefile +75 -0
  4. data/ideas.md +29 -0
  5. data/lib/sinatra/capture.rb +124 -0
  6. data/lib/sinatra/config_file.rb +167 -0
  7. data/lib/sinatra/content_for.rb +125 -0
  8. data/lib/sinatra/contrib.rb +39 -0
  9. data/lib/sinatra/contrib/all.rb +2 -0
  10. data/lib/sinatra/contrib/setup.rb +53 -0
  11. data/lib/sinatra/contrib/version.rb +17 -0
  12. data/lib/sinatra/cookies.rb +331 -0
  13. data/lib/sinatra/decompile.rb +120 -0
  14. data/lib/sinatra/engine_tracking.rb +96 -0
  15. data/lib/sinatra/extension.rb +95 -0
  16. data/lib/sinatra/json.rb +130 -0
  17. data/lib/sinatra/link_header.rb +132 -0
  18. data/lib/sinatra/multi_route.rb +87 -0
  19. data/lib/sinatra/namespace.rb +284 -0
  20. data/lib/sinatra/reloader.rb +394 -0
  21. data/lib/sinatra/respond_with.rb +249 -0
  22. data/lib/sinatra/streaming.rb +267 -0
  23. data/lib/sinatra/test_helpers.rb +87 -0
  24. data/sinatra-contrib.gemspec +127 -0
  25. data/spec/capture_spec.rb +93 -0
  26. data/spec/config_file/key_value.yml +6 -0
  27. data/spec/config_file/key_value.yml.erb +6 -0
  28. data/spec/config_file/key_value_override.yml +2 -0
  29. data/spec/config_file/missing_env.yml +4 -0
  30. data/spec/config_file/with_envs.yml +7 -0
  31. data/spec/config_file/with_nested_envs.yml +11 -0
  32. data/spec/config_file_spec.rb +63 -0
  33. data/spec/content_for/different_key.erb +1 -0
  34. data/spec/content_for/different_key.erubis +1 -0
  35. data/spec/content_for/different_key.haml +2 -0
  36. data/spec/content_for/different_key.slim +2 -0
  37. data/spec/content_for/layout.erb +1 -0
  38. data/spec/content_for/layout.erubis +1 -0
  39. data/spec/content_for/layout.haml +1 -0
  40. data/spec/content_for/layout.slim +1 -0
  41. data/spec/content_for/multiple_blocks.erb +4 -0
  42. data/spec/content_for/multiple_blocks.erubis +4 -0
  43. data/spec/content_for/multiple_blocks.haml +8 -0
  44. data/spec/content_for/multiple_blocks.slim +8 -0
  45. data/spec/content_for/multiple_yields.erb +3 -0
  46. data/spec/content_for/multiple_yields.erubis +3 -0
  47. data/spec/content_for/multiple_yields.haml +3 -0
  48. data/spec/content_for/multiple_yields.slim +3 -0
  49. data/spec/content_for/passes_values.erb +1 -0
  50. data/spec/content_for/passes_values.erubis +1 -0
  51. data/spec/content_for/passes_values.haml +1 -0
  52. data/spec/content_for/passes_values.slim +1 -0
  53. data/spec/content_for/same_key.erb +1 -0
  54. data/spec/content_for/same_key.erubis +1 -0
  55. data/spec/content_for/same_key.haml +2 -0
  56. data/spec/content_for/same_key.slim +2 -0
  57. data/spec/content_for/takes_values.erb +1 -0
  58. data/spec/content_for/takes_values.erubis +1 -0
  59. data/spec/content_for/takes_values.haml +3 -0
  60. data/spec/content_for/takes_values.slim +3 -0
  61. data/spec/content_for_spec.rb +213 -0
  62. data/spec/cookies_spec.rb +802 -0
  63. data/spec/decompile_spec.rb +44 -0
  64. data/spec/extension_spec.rb +33 -0
  65. data/spec/json_spec.rb +117 -0
  66. data/spec/link_header_spec.rb +100 -0
  67. data/spec/multi_route_spec.rb +60 -0
  68. data/spec/namespace/foo.erb +1 -0
  69. data/spec/namespace/nested/foo.erb +1 -0
  70. data/spec/namespace_spec.rb +676 -0
  71. data/spec/okjson.rb +581 -0
  72. data/spec/reloader/app.rb.erb +40 -0
  73. data/spec/reloader_spec.rb +441 -0
  74. data/spec/respond_with/bar.erb +1 -0
  75. data/spec/respond_with/bar.json.erb +1 -0
  76. data/spec/respond_with/foo.html.erb +1 -0
  77. data/spec/respond_with/not_html.sass +2 -0
  78. data/spec/respond_with_spec.rb +297 -0
  79. data/spec/spec_helper.rb +7 -0
  80. data/spec/streaming_spec.rb +436 -0
  81. metadata +313 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011 Nicolas Sanguinetti, entp.com, Konstantin Haase
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,136 @@
1
+ [![Build Status](https://secure.travis-ci.org/sinatra/sinatra-contrib.png)](http://travis-ci.org/sinatra/sinatra-contrib)
2
+
3
+ Collection of common Sinatra extensions, semi-officially supported.
4
+
5
+ # Goals
6
+
7
+ * For every future Sinatra release, have at least one fully compatible release
8
+ * High code quality, high test coverage
9
+ * Include plugins people usually ask for a lot
10
+
11
+ # Included extensions
12
+
13
+ ## Common Extensions
14
+
15
+ These are common extension which will not add significant overhead or change any
16
+ behavior of already existing APIs. They do not add any dependencies not already
17
+ installed with this gem.
18
+
19
+ Currently included:
20
+
21
+ * `sinatra/capture`: Let's you capture the content of blocks in templates.
22
+
23
+ * `sinatra/config_file`: Allows loading configuration from yaml files.
24
+
25
+ * `sinatra/content_for`: Adds Rails-style `content_for` helpers to Haml, Erb,
26
+ Erubis and Slim.
27
+
28
+ * `sinatra/cookies`: A `cookies` helper for reading and writing cookies.
29
+
30
+ * `sinatra/engine_tracking`: Adds methods like `haml?` that allow helper
31
+ methods to check whether they are called from within a template.
32
+
33
+ * `sinatra/json`: Adds a `#json` helper method to return JSON documents.
34
+
35
+ * `sinatra/link_header`: Helpers for generating `link` HTML tags and
36
+ corresponding `Link` HTTP headers. Adds `link`, `stylesheet` and `prefetch`
37
+ helper methods.
38
+
39
+ * `sinatra/multi_route`: Adds ability to define one route block for multiple
40
+ routes and multiple or custom HTTP verbs.
41
+
42
+ * `sinatra/namespace`: Adds namespace support to Sinatra.
43
+
44
+ * `sinatra/respond_with`: Choose action and/or template automatically
45
+ depending on the incoming request. Adds helpers `respond_to` and
46
+ `respond_with`.
47
+
48
+
49
+ ## Custom Extensions
50
+
51
+ These extensions may add additional dependencies and enhance the behavior of the
52
+ existing APIs.
53
+
54
+ Currently included:
55
+
56
+ * `sinatra/decompile`: Recreates path patterns from Sinatra's internal data
57
+ structures (used by other extensions).
58
+
59
+ * `sinatra/reloader`: Automatically reloads Ruby files on code changes.
60
+
61
+ ## Other Tools
62
+
63
+ * `sinatra/extension`: Mixin for writing your own Sinatra extensions.
64
+
65
+ * `sinatra/test_helpers`: Helper methods to ease testing your Sinatra
66
+ application. Partly extracted from Sinatra. Testing framework agnostic
67
+
68
+ # Installation
69
+ Add `gem 'sinatra-contrib'` to *Gemfile*, then execute `bundle install`.
70
+
71
+ If you don't use Bundler, install the gem manually by executing `gem install sinatra-contrib` in your command line.
72
+
73
+
74
+ # Usage
75
+
76
+ ## Classic Style
77
+
78
+ A single extension (example: sinatra-content-for):
79
+
80
+ ``` ruby
81
+ require 'sinatra'
82
+ require 'sinatra/content_for'
83
+ ```
84
+
85
+ Common extensions:
86
+
87
+ ``` ruby
88
+ require 'sinatra'
89
+ require 'sinatra/contrib'
90
+ ```
91
+
92
+ All extensions:
93
+
94
+ ``` ruby
95
+ require 'sinatra'
96
+ require 'sinatra/contrib/all'
97
+ ```
98
+
99
+ ## Modular Style
100
+
101
+ A single extension (example: sinatra-content-for):
102
+
103
+ ``` ruby
104
+ require 'sinatra/base'
105
+ require 'sinatra/content_for'
106
+ require 'sinatra/namespace'
107
+
108
+ class MyApp < Sinatra::Base
109
+ # Note: Some modules are extensions, some helpers, see the specific
110
+ # documentation or the source
111
+ helpers Sinatra::ContentFor
112
+ register Sinatra::Namespace
113
+ end
114
+ ```
115
+
116
+ Common extensions:
117
+
118
+ ``` ruby
119
+ require 'sinatra/base'
120
+ require 'sinatra/contrib'
121
+
122
+ class MyApp < Sinatra::Base
123
+ register Sinatra::Contrib
124
+ end
125
+ ```
126
+
127
+ All extensions:
128
+
129
+ ``` ruby
130
+ require 'sinatra/base'
131
+ require 'sinatra/contrib/all'
132
+
133
+ class MyApp < Sinatra::Base
134
+ register Sinatra::Contrib
135
+ end
136
+ ```
@@ -0,0 +1,75 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'open-uri'
3
+ require 'yaml'
4
+ require 'sinatra/contrib/version'
5
+
6
+ desc "run specs"
7
+ task(:spec) { ruby '-S rspec spec -c' }
8
+ task(:test => :spec)
9
+ task(:default => :spec)
10
+
11
+ namespace :doc do
12
+ task :readmes do
13
+ Dir.glob 'lib/sinatra/*.rb' do |file|
14
+ excluded_files = %w[lib/sinatra/contrib.rb lib/sinatra/capture.rb lib/sinatra/engine_tracking.rb]
15
+ next if excluded_files.include?(file)
16
+ doc = File.read(file)[/^module Sinatra(\n)+( #[^\n]*\n)*/m].scan(/^ *#(?!#) ?(.*)\n/).join("\n")
17
+ file = "doc/#{file[4..-4].tr("/_", "-")}.rdoc"
18
+ Dir.mkdir "doc" unless File.directory? "doc"
19
+ puts "writing #{file}"
20
+ File.open(file, "w") { |f| f << doc }
21
+ end
22
+ end
23
+
24
+ task :all => [:readmes]
25
+ end
26
+
27
+ desc "generate documentation"
28
+ task :doc => 'doc:all'
29
+
30
+ desc "generate gemspec"
31
+ task 'sinatra-contrib.gemspec' do
32
+ content = File.read 'sinatra-contrib.gemspec'
33
+
34
+ fields = {
35
+ :authors => `git shortlog -sn`.scan(/[^\d\s].*/),
36
+ :email => `git shortlog -sne`.scan(/[^<]+@[^>]+/),
37
+ :files => `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ }
38
+ }
39
+
40
+ fields.each do |field, values|
41
+ updated = " s.#{field} = ["
42
+ updated << values.map { |v| "\n %p" % v }.join(',')
43
+ updated << "\n ]"
44
+ content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated)
45
+ end
46
+
47
+ content.sub! /(s\.version.*=\s+).*/, "\\1\"#{Sinatra::Contrib::VERSION}\""
48
+ File.open('sinatra-contrib.gemspec', 'w') { |f| f << content }
49
+ end
50
+
51
+ task :gemspec => 'sinatra-contrib.gemspec'
52
+
53
+ desc 'update travis config to correspond to sinatra'
54
+ task :travis, [:branch] do |t, a|
55
+ a.with_defaults :branch => :master
56
+ data = YAML.load open("https://raw.github.com/sinatra/sinatra/#{a.branch}/.travis.yml")
57
+ data["notifications"]["recipients"] << "ohhgabriel@gmail.com"
58
+ File.open('.travis.yml', 'w') { |f| f << data.to_yaml }
59
+ system 'git add .travis.yml && git diff --cached .travis.yml'
60
+ end
61
+
62
+ task :release => :gemspec do
63
+ sh <<-SH
64
+ rm -Rf sinatra-contrib*.gem &&
65
+ gem build sinatra-contrib.gemspec &&
66
+ gem install sinatra-contrib*.gem --local &&
67
+ gem push sinatra-contrib*.gem &&
68
+ git commit --allow-empty -a -m '#{Sinatra::Contrib::VERSION} release' &&
69
+ git tag -s v#{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
70
+ git tag -s #{Sinatra::Contrib::VERSION} -m '#{Sinatra::Contrib::VERSION} release' &&
71
+ git push && (git push sinatra || true) &&
72
+ git push --tags && (git push sinatra --tags || true)
73
+ SH
74
+ end
75
+
@@ -0,0 +1,29 @@
1
+ * Extension that does something like this:
2
+
3
+ def build(*)
4
+ if settings.memcached?
5
+ use Rack::Cache, :backend => :memcached
6
+ use Rack::Session::Memcached
7
+ # ...
8
+ end
9
+ super
10
+ end
11
+
12
+ * `sinatra-smart-cache`: update cache header only if arguments are more
13
+ restrictive than curent value, set caching headers that way for most helper
14
+ methods (i.e. `sass` or `send_file`)
15
+
16
+ * Some verbose logging extension: Log what filters, routes, error handlers,
17
+ templates, and so on is used.
18
+
19
+ * Form helpers, with forms as first class objects that accepts hashes or
20
+ something, so the form meta data can also be used to expose a JSON API or
21
+ similar, possibly defining routes (like "Sinatra's Hat"), strictly using
22
+ the ActiveModel API.
23
+
24
+ * Extend `sinatra-content-for` to support Liquid, Radius, Markaby, Nokogiri and
25
+ Builder. At least the first two probably involve patching Tilt.
26
+
27
+ * Rewrite of `sinatra-compass`?
28
+
29
+ * Helpers for HTML escaping and such.
@@ -0,0 +1,124 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/engine_tracking'
3
+ require 'backports'
4
+
5
+ module Sinatra
6
+ #
7
+ # = Sinatra::Capture
8
+ #
9
+ # Extension that enables blocks inside other extensions.
10
+ # It currently works for erb, slim and haml.
11
+ # Enables mixing of different template languages.
12
+ #
13
+ # Example:
14
+ #
15
+ # # in hello_world.erb
16
+ #
17
+ # Say
18
+ # <% a = capture do %>World<% end %>
19
+ # Hello <%= a %>!
20
+ #
21
+ # # in hello_world.slim
22
+ #
23
+ # | Say
24
+ # - a = capture do
25
+ # | World
26
+ # | Hello #{a}!
27
+ #
28
+ # # in hello_world.haml
29
+ #
30
+ # Say
31
+ # - a = capture do
32
+ # World
33
+ # Hello #{a.strip}!
34
+ #
35
+ #
36
+ # You can also use nested blocks.
37
+ #
38
+ # Example
39
+ #
40
+ # # in hello_world.erb
41
+ #
42
+ # Say
43
+ # <% a = capture do %>
44
+ # <% b = capture do %>World<% end %>
45
+ # <%= b %>!
46
+ # <% end %>
47
+ # Hello <%= a.strip %>
48
+ #
49
+ #
50
+ # The main advantage of capture is mixing of different template engines.
51
+ #
52
+ # Example
53
+ #
54
+ # # in mix_me_up.slim
55
+ #
56
+ # - two = capture do
57
+ # - erb "<%= 1 + 1 %>"
58
+ # | 1 + 1 = #{two}
59
+ #
60
+ # == Usage
61
+ #
62
+ # === Classic Application
63
+ #
64
+ # In a classic application simply require the helpers, and start using them:
65
+ #
66
+ # require "sinatra"
67
+ # require "sinatra/capture"
68
+ #
69
+ # # The rest of your classic application code goes here...
70
+ #
71
+ # === Modular Application
72
+ #
73
+ # In a modular application you need to require the helpers, and then tell
74
+ # the application you will use them:
75
+ #
76
+ # require "sinatra/base"
77
+ # require "sinatra/capture"
78
+ #
79
+ # class MyApp < Sinatra::Base
80
+ # helpers Sinatra::Capture
81
+ #
82
+ # # The rest of your modular application code goes here...
83
+ # end
84
+ #
85
+ module Capture
86
+ include Sinatra::EngineTracking
87
+
88
+ DUMMIES = {
89
+ :haml => "!= capture_haml(*args, &block)",
90
+ :erubis => "<% @capture = yield(*args) %>",
91
+ :slim => "== yield(*args)"
92
+ }
93
+
94
+ def capture(*args, &block)
95
+ @capture = nil
96
+ if current_engine == :ruby
97
+ result = block[*args]
98
+ elsif current_engine == :erb
99
+ @_out_buf, _buf_was = '', @_out_buf
100
+ block[*args]
101
+ result = eval('@_out_buf', block.binding)
102
+ @_out_buf = _buf_was
103
+ else
104
+ buffer = eval '_buf if defined?(_buf)', block.binding
105
+ old_buffer = buffer.dup if buffer
106
+ dummy = DUMMIES.fetch(current_engine)
107
+ options = { :layout => false, :locals => {:args => args, :block => block }}
108
+
109
+ buffer.try :clear
110
+ result = render(current_engine, dummy, options, &block)
111
+ end
112
+ result.strip.empty? && @capture ? @capture : result
113
+ ensure
114
+ buffer.try :replace, old_buffer
115
+ end
116
+
117
+ def capture_later(&block)
118
+ engine = current_engine
119
+ proc { |*a| with_engine(engine) { @capture = capture(*a, &block) }}
120
+ end
121
+ end
122
+
123
+ helpers Capture
124
+ end
@@ -0,0 +1,167 @@
1
+ require 'sinatra/base'
2
+ require 'yaml'
3
+ require 'erb'
4
+
5
+ module Sinatra
6
+
7
+ # = Sinatra::ConfigFile
8
+ #
9
+ # <tt>Sinatra::ConfigFile</tt> is an extension that allows you to load the
10
+ # application's configuration from YAML files. It automatically detects if
11
+ # the files contains specific environment settings and it will use the
12
+ # corresponding to the current one.
13
+ #
14
+ # You can access those options through +settings+ within the application. If
15
+ # you try to get the value for a setting that hasn't been defined in the
16
+ # config file for the current environment, you will get whatever it was set
17
+ # to in the application.
18
+ #
19
+ # == Usage
20
+ #
21
+ # Once you have written your configurations to a YAML file you can tell the
22
+ # extension to load them. See below for more information about how these
23
+ # files are interpreted.
24
+ #
25
+ # For the examples, lets assume the following config.yml file:
26
+ #
27
+ # greeting: Welcome to my file configurable application
28
+ #
29
+ # === Classic Application
30
+ #
31
+ # require "sinatra"
32
+ # require "sinatra/config_file"
33
+ #
34
+ # config_file 'path/to/config.yml'
35
+ #
36
+ # get '/' do
37
+ # @greeting = settings.greeting
38
+ # haml :index
39
+ # end
40
+ #
41
+ # # The rest of your classic application code goes here...
42
+ #
43
+ # === Modular Application
44
+ #
45
+ # require "sinatra/base"
46
+ # require "sinatra/config_file"
47
+ #
48
+ # class MyApp < Sinatra::Base
49
+ # register Sinatra::ConfigFile
50
+ #
51
+ # config_file 'path/to/config.yml'
52
+ #
53
+ # get '/' do
54
+ # @greeting = settings.greeting
55
+ # haml :index
56
+ # end
57
+ #
58
+ # # The rest of your modular application code goes here...
59
+ # end
60
+ #
61
+ # === Config File Format
62
+ #
63
+ # In its most simple form this file is just a key-value list:
64
+ #
65
+ # foo: bar
66
+ # something: 42
67
+ # nested:
68
+ # a: 1
69
+ # b: 2
70
+ #
71
+ # But it also can provide specific environment configuration. There are two
72
+ # ways to do that: at the file level and at the setting level. They are
73
+ # illustrated, repsectively, as follows:
74
+ #
75
+ # development:
76
+ # foo: development
77
+ # bar: bar
78
+ # test:
79
+ # foo: test
80
+ # bar: bar
81
+ # production:
82
+ # foo: production
83
+ # bar: bar
84
+ #
85
+ # and
86
+ #
87
+ # foo:
88
+ # development: development
89
+ # test: test
90
+ # production: production
91
+ # bar: bar
92
+ #
93
+ # In either case, <tt>settings.foo</tt> will return the environment name, and
94
+ # <tt>settings.bar</tt> will return <tt>"bar"</tt>.
95
+ #
96
+ # Be aware that if you have a different environment, besides development,
97
+ # test and production, you will also need to adjust the +environments+
98
+ # setting, otherwise the settings will not load. For instance, when
99
+ # you also have a staging environment:
100
+ #
101
+ # set :environments, %w{development test production staging}
102
+ #
103
+ # If you wish to provide defaults that may be shared among all the environments,
104
+ # this can be done by using one of the existing environments as the default using
105
+ # the YAML alias, and then overwriting values in the other environments:
106
+ #
107
+ # development: &common_settings
108
+ # foo: 'foo'
109
+ # bar: 'bar'
110
+ #
111
+ # production:
112
+ # <<: *common_settings
113
+ # bar: 'baz' # override the default value
114
+ #
115
+ module ConfigFile
116
+
117
+ # When the extension is registered sets the +environments+ setting to the
118
+ # traditional environments: development, test and production.
119
+ def self.registered(base)
120
+ base.set :environments, %w[test production development]
121
+ end
122
+
123
+ # Loads the configuration from the YAML files whose +paths+ are passed as
124
+ # arguments, filtering the settings for the current environment. Note that
125
+ # these +paths+ can actually be globs.
126
+ def config_file(*paths)
127
+ Dir.chdir(root || '.') do
128
+ paths.each do |pattern|
129
+ Dir.glob(pattern) do |file|
130
+ $stderr.puts "loading config file '#{file}'" if logging?
131
+ document = IO.read(file)
132
+ document = ERB.new(document).result if file.split('.').include?('erb')
133
+ yaml = config_for_env(YAML.load(document)) || {}
134
+ yaml.each_pair do |key, value|
135
+ for_env = config_for_env(value)
136
+ set key, for_env unless value and for_env.nil? and respond_to? key
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ # Given a +hash+ with some application configuration it returns the
146
+ # settings applicable to the current environment. Note that this can only
147
+ # be done when all the keys of +hash+ are environment names included in the
148
+ # +environments+ setting (which is an Array of Strings). Also, the
149
+ # returned config is a indifferently accessible Hash, which means that you
150
+ # can get its values using Strings or Symbols as keys.
151
+ def config_for_env(hash)
152
+ if hash.respond_to? :keys and hash.keys.all? { |k| environments.include? k.to_s }
153
+ hash = hash[environment.to_s] || hash[environment.to_sym]
154
+ end
155
+
156
+ if hash.respond_to? :to_hash
157
+ indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
158
+ indifferent_hash.merge hash.to_hash
159
+ else
160
+ hash
161
+ end
162
+ end
163
+ end
164
+
165
+ register ConfigFile
166
+ Delegator.delegate :config_file
167
+ end