mguymon-figaro 0.7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.travis.yml +19 -0
- data/Gemfile +13 -0
- data/LICENSE +22 -0
- data/README.md +139 -0
- data/Rakefile +6 -0
- data/figaro.gemspec +20 -0
- data/gemfiles/rails30.gemfile +11 -0
- data/gemfiles/rails31.gemfile +11 -0
- data/gemfiles/rails32.gemfile +11 -0
- data/gemfiles/rails40.gemfile +11 -0
- data/lib/figaro.rb +26 -0
- data/lib/figaro/application.rb +77 -0
- data/lib/figaro/env.rb +37 -0
- data/lib/figaro/error.rb +6 -0
- data/lib/figaro/rails.rb +9 -0
- data/lib/figaro/rails/application.rb +21 -0
- data/lib/figaro/rails/railtie.rb +13 -0
- data/lib/figaro/rails/tasks.rake +6 -0
- data/lib/figaro/tasks.rb +28 -0
- data/lib/generators/figaro/install/install_generator.rb +23 -0
- data/lib/generators/figaro/install/templates/application.yml +7 -0
- data/spec/figaro/application_spec.rb +244 -0
- data/spec/figaro/env_spec.rb +177 -0
- data/spec/figaro/rails/application_spec.rb +43 -0
- data/spec/figaro/tasks_spec.rb +71 -0
- data/spec/figaro_spec.rb +62 -0
- data/spec/rails_spec.rb +67 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/aruba.rb +10 -0
- data/spec/support/rake.rb +11 -0
- data/spec/support/reset.rb +6 -0
- metadata +127 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
before_script:
|
2
|
+
- unset RAILS_ENV
|
3
|
+
- unset RACK_ENV
|
4
|
+
branches: master
|
5
|
+
gemfile:
|
6
|
+
- gemfiles/rails30.gemfile
|
7
|
+
- gemfiles/rails31.gemfile
|
8
|
+
- gemfiles/rails32.gemfile
|
9
|
+
- gemfiles/rails40.gemfile
|
10
|
+
language: ruby
|
11
|
+
matrix:
|
12
|
+
include:
|
13
|
+
- gemfile: Gemfile
|
14
|
+
rvm: 2.0.0
|
15
|
+
env: COVERAGE=1
|
16
|
+
rvm:
|
17
|
+
- 1.9.3
|
18
|
+
- 2.0.0
|
19
|
+
script: rspec
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Steve Richert
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Figaro
|
2
|
+
[](http://badge.fury.io/rb/figaro)
|
3
|
+
[](https://travis-ci.org/laserlemon/figaro)
|
4
|
+
[](https://codeclimate.com/github/laserlemon/figaro)
|
5
|
+
[](https://coveralls.io/r/laserlemon/figaro)
|
6
|
+
[](https://gemnasium.com/laserlemon/figaro)
|
7
|
+
|
8
|
+
Simple Rails app configuration
|
9
|
+
|
10
|
+
## What is this for?
|
11
|
+
|
12
|
+
Figaro is for configuring Rails (3 and 4) apps, especially open source Rails apps.
|
13
|
+
|
14
|
+
Open sourcing a Rails app can be a little tricky when it comes to sensitive configuration information like [Pusher](http://pusher.com/) or [Stripe](https://stripe.com/) credentials. You don't want to check private credentials into the repo but what other choice is there?
|
15
|
+
|
16
|
+
Figaro provides a clean and simple way to configure your app and keep the private stuff… private.
|
17
|
+
|
18
|
+
## How does it work?
|
19
|
+
|
20
|
+
There are a few similar solutions out there, and a lot of homegrown attempts. Most namespace your configuration under a `Config` (or similar) namespace. That's fine, but there's already a place to describe the application environment… `ENV`!
|
21
|
+
|
22
|
+
`ENV` is a collection of simple string key/value pairs and it works just great for application configuration.
|
23
|
+
|
24
|
+
As an added bonus, this is exactly how apps on [Heroku](http://www.heroku.com/) are configured. So if you configure your Rails app using `ENV`, you're already set to deploy to Heroku.
|
25
|
+
|
26
|
+
## Give me an example.
|
27
|
+
|
28
|
+
Okay. Add Figaro to your Gemfile and run the `bundle` command to install it:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
gem "figaro"
|
32
|
+
```
|
33
|
+
|
34
|
+
Next up, use the generator provided by Figaro:
|
35
|
+
|
36
|
+
```bash
|
37
|
+
rails generate figaro:install
|
38
|
+
```
|
39
|
+
|
40
|
+
This creates a commented `config/application.yml` file and ignores it in your `.gitignore`. Add your own configuration to this file and you're done!
|
41
|
+
|
42
|
+
Your configuration will be available as key/value pairs in `ENV`. For example, here's `config/initializers/pusher.rb`:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Pusher.app_id = ENV["PUSHER_APP_ID"]
|
46
|
+
Pusher.key = ENV["PUSHER_KEY"]
|
47
|
+
Pusher.secret = ENV["PUSHER_SECRET"]
|
48
|
+
```
|
49
|
+
|
50
|
+
In addition, you can access these same configuration values through Figaro itself:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Pusher.app_id = Figaro.env.pusher_app_id
|
54
|
+
Pusher.key = Figaro.env.pusher_key
|
55
|
+
Pusher.secret = Figaro.env.pusher_secret
|
56
|
+
```
|
57
|
+
|
58
|
+
But wait… I thought configuration via constant was bad! Well, this is different. Rather than storing a _copy_ of `ENV` internally, `Figaro.env` passes directly through to `ENV`, making it just like using `ENV` itself. So why two approaches? Having your configurations available via method calls makes it easy to stub them out in tests. Either way is fine. The choice is yours!
|
59
|
+
|
60
|
+
If your app requires Rails-environment-specific configuration, you can also namespace your configuration under a key for `Rails.env`.
|
61
|
+
|
62
|
+
```yaml
|
63
|
+
HELLO: world
|
64
|
+
development:
|
65
|
+
HELLO: developers
|
66
|
+
production:
|
67
|
+
HELLO: users
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
In this case, `ENV["HELLO"]` will produce `"developers"` in development, `"users"` in production and `"world"` otherwise.
|
72
|
+
|
73
|
+
**NOTE:** Figaro uses Rails' standard hooks to initialize. Unfortunately, this hook apparently occurs after `database.yml` is read. Because of this issue, environment variables created in `application.yml` don't work inside `database.yml`.
|
74
|
+
|
75
|
+
|
76
|
+
## How does it work with Heroku?
|
77
|
+
|
78
|
+
Heroku's beautifully simple application configuration was the [inspiration](http://laserlemon.com/blog/2011/03/08/heroku-friendly-application-configuration/) for Figaro.
|
79
|
+
|
80
|
+
Typically, to configure your application `ENV` on Heroku, you would do the following from the command line using the `heroku` gem:
|
81
|
+
|
82
|
+
```bash
|
83
|
+
heroku config:add PUSHER_APP_ID=8926
|
84
|
+
heroku config:add PUSHER_KEY=0463644d89a340ff1132
|
85
|
+
heroku config:add PUSHER_SECRET=0eadfd9847769f94367b
|
86
|
+
heroku config:add STRIPE_API_KEY=jHXKPPE0dUW84xJNYzn6CdWM2JfrCbPE
|
87
|
+
heroku config:add STRIPE_PUBLIC_KEY=pk_HHtUKJwlN7USCT6nE5jiXgoduiNl3
|
88
|
+
```
|
89
|
+
|
90
|
+
But Figaro provides a rake task to do just that! Just run:
|
91
|
+
|
92
|
+
```bash
|
93
|
+
rake figaro:heroku
|
94
|
+
```
|
95
|
+
|
96
|
+
Optionally, you can pass in the name of the Heroku app:
|
97
|
+
|
98
|
+
```bash
|
99
|
+
rake figaro:heroku[my-awesome-app]
|
100
|
+
```
|
101
|
+
|
102
|
+
Additionally, if `RAILS_ENV` is configured on your Heroku server, Figaro will use that environment automatically in determining your proper configuration.
|
103
|
+
|
104
|
+
## What if I'm not using Heroku?
|
105
|
+
|
106
|
+
No problem. Just add `config/application.yml` to your production app on the server.
|
107
|
+
|
108
|
+
## This sucks. How can I make it better?
|
109
|
+
|
110
|
+
1. Fork it.
|
111
|
+
2. Make it better.
|
112
|
+
3. Send me a pull request.
|
113
|
+
|
114
|
+
## Does Figaro have a mascot?
|
115
|
+
|
116
|
+
Yes.
|
117
|
+
|
118
|
+
[](http://en.wikipedia.org/wiki/Figaro_(Disney\))
|
119
|
+
|
120
|
+
## Thank you!
|
121
|
+
|
122
|
+
Figaro is made possible by the continued contributions and insights from kind-hearted developers everywhere. Just to name a few:
|
123
|
+
|
124
|
+
* [@ersatzryan](https://github.com/ersatzryan)
|
125
|
+
* [@robertjwhitney](https://github.com/robertjwhitney)
|
126
|
+
* [@maxwell](https://github.com/maxwell)
|
127
|
+
* [@GuilhermeSimoes](https://github.com/GuilhermeSimoes)
|
128
|
+
* [@mikeycgto](https://github.com/mikeycgto)
|
129
|
+
* [@subosito](https://github.com/subosito)
|
130
|
+
* [@srushti](https://github.com/srushti)
|
131
|
+
* [@ptyagi16](https://github.com/ptyagi16)
|
132
|
+
* [@jspradlin](https://github.com/jspradlin)
|
133
|
+
* [@hadifarnoud](https://github.com/hadifarnoud)
|
134
|
+
* [@eloyesp](https://github.com/eloyesp)
|
135
|
+
* [@etuya-ix](https://github.com/etuya-ix)
|
136
|
+
* [@MarkDBlackwell](https://github.com/MarkDBlackwell)
|
137
|
+
* [@HALapeno](https://github.com/HALapeno)
|
138
|
+
* [@severin](https://github.com/severin)
|
139
|
+
* [@sethvargo](https://github.com/sethvargo)
|
data/Rakefile
ADDED
data/figaro.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "mguymon-figaro"
|
5
|
+
gem.version = "0.7.0.1"
|
6
|
+
|
7
|
+
gem.author = "Steve Richert"
|
8
|
+
gem.email = "steve.richert@gmail.com"
|
9
|
+
gem.summary = "Simple Rails app configuration"
|
10
|
+
gem.description = "Simple, Heroku-friendly Rails app configuration using ENV and a single YAML file"
|
11
|
+
gem.homepage = "https://github.com/laserlemon/figaro"
|
12
|
+
gem.license = "MIT"
|
13
|
+
|
14
|
+
gem.add_dependency "bundler", "~> 1.0"
|
15
|
+
gem.add_dependency "rails", ">= 3", "< 5"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($\)
|
18
|
+
gem.test_files = gem.files.grep(/^(features|spec)/)
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
end
|
data/lib/figaro.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "figaro/application"
|
2
|
+
require "figaro/env"
|
3
|
+
require "figaro/rails"
|
4
|
+
require "figaro/tasks"
|
5
|
+
|
6
|
+
module Figaro
|
7
|
+
extend self
|
8
|
+
|
9
|
+
attr_writer :backend, :application
|
10
|
+
|
11
|
+
def env
|
12
|
+
Figaro::ENV
|
13
|
+
end
|
14
|
+
|
15
|
+
def backend
|
16
|
+
@backend ||= Figaro::Rails::Application
|
17
|
+
end
|
18
|
+
|
19
|
+
def application
|
20
|
+
@application ||= backend.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def load
|
24
|
+
application.load
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
require "figaro/error"
|
5
|
+
|
6
|
+
module Figaro
|
7
|
+
class Application
|
8
|
+
FIGARO_ENV_PREFIX = "FIGARO_"
|
9
|
+
|
10
|
+
attr_writer :path, :environment
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@path = options[:path]
|
14
|
+
@environment = options[:environment]
|
15
|
+
end
|
16
|
+
|
17
|
+
def path
|
18
|
+
(@path || default_path).to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def environment
|
22
|
+
(@environment || default_environment).to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def configuration
|
26
|
+
global_configuration.merge(environment_configuration)
|
27
|
+
end
|
28
|
+
|
29
|
+
def load
|
30
|
+
configuration.each do |key, value|
|
31
|
+
set(key, value) unless skip?(key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def default_path
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_environment
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_configuration
|
46
|
+
(@parsed ||= Hash.new { |hash, path| hash[path] = parse(path) })[path]
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse(path)
|
50
|
+
File.exist?(path) && YAML.load(ERB.new(File.read(path)).result) || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def global_configuration
|
54
|
+
raw_configuration.reject { |_, value| value.is_a?(Hash) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def environment_configuration
|
58
|
+
raw_configuration.fetch(environment) { {} }
|
59
|
+
end
|
60
|
+
|
61
|
+
def set(key, value)
|
62
|
+
non_string_configuration!(key) unless key.is_a?(String)
|
63
|
+
non_string_configuration!(value) unless value.is_a?(String)
|
64
|
+
|
65
|
+
::ENV[key.to_s] = value.to_s
|
66
|
+
::ENV[FIGARO_ENV_PREFIX + key.to_s] = value.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
def skip?(key)
|
70
|
+
::ENV.key?(key.to_s) && !::ENV.key?(FIGARO_ENV_PREFIX + key.to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
def non_string_configuration!(value)
|
74
|
+
warn "WARNING: Use strings for Figaro configuration. #{value.inspect} was converted to #{value.to_s.inspect}."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/figaro/env.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Figaro
|
2
|
+
module ENV
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def respond_to?(method, *)
|
6
|
+
key, punctuation = extract_key_from_method(method)
|
7
|
+
|
8
|
+
case punctuation
|
9
|
+
when "!" then ::ENV.keys.any? { |k| k.upcase == key } || super
|
10
|
+
when "?", nil then true
|
11
|
+
else super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def method_missing(method, *)
|
18
|
+
key, punctuation = extract_key_from_method(method)
|
19
|
+
_, value = ::ENV.detect { |k, _| k.upcase == key }
|
20
|
+
|
21
|
+
case punctuation
|
22
|
+
when "!" then value || missing_key!(key)
|
23
|
+
when "?" then !!value
|
24
|
+
when nil then value
|
25
|
+
else super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_key_from_method(method)
|
30
|
+
method.to_s.upcase.match(/^(.+?)([!?=])?$/).captures
|
31
|
+
end
|
32
|
+
|
33
|
+
def missing_key!(key)
|
34
|
+
raise MissingKey.new("Missing required Figaro configuration key #{key.inspect}.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/figaro/error.rb
ADDED