mguymon-figaro 0.7.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/figaro.png)](http://badge.fury.io/rb/figaro)
|
3
|
+
[![Build Status](https://travis-ci.org/laserlemon/figaro.png?branch=master)](https://travis-ci.org/laserlemon/figaro)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/laserlemon/figaro.png)](https://codeclimate.com/github/laserlemon/figaro)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/laserlemon/figaro/badge.png?branch=master)](https://coveralls.io/r/laserlemon/figaro)
|
6
|
+
[![Dependency Status](https://gemnasium.com/laserlemon/figaro.png)](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
|
+
[![Figaro](http://images2.wikia.nocookie.net/__cb20100628192722/disney/images/5/53/Pinocchio-pinocchio-4947890-960-720.jpg "Figaro's mascot: Figaro")](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